好久没做算法题了,偶然看到一道题练练手。(顺便复习一下markdown)
题目:
用m个相同鸡蛋测n层楼,要测出鸡蛋硬度具体能抗几层楼高,问最少要测试几次(即丢几次鸡蛋)。
题目解析:
是一道很简单的题目的延申?考虑一种较为简单的情况:100层楼,2个鸡蛋,此时假设让第一个鸡蛋在x楼落下(显然,1<=x<=n),则可能出现以下两种情况:
1)鸡蛋摔碎,那么后续只需要在下面的x-1个楼层继续测试,则问题变成了x-1层楼,2-1=1个鸡蛋;
2)鸡蛋未摔碎,那么后续只需要在上面的100-x个楼层继续测试,则问题变成了100-x层楼,2个鸡蛋;
由于以上两种情况均可能发生,所以我们自然要取两个问题之解中的最大值啦。
!不要忘记已经摔了一次了!
于是这就非常顺理成章地变成了一个dp[1]问题!
然后考虑一下边界情况:
·如果只剩下0层楼,那显然不用再试了;
·如果只剩下0个鸡蛋,那显然也不用再试了;(中华文化博大精深)
·由于0个鸡蛋对应的测试次数是无穷大,无法推导出1个鸡蛋时的测试次数,因此对于鸡蛋个数的边界应该是1个鸡蛋的情况,此时显然只能从1楼一层层往上走,要丢n次;
于是dp就完成啦!
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int hardness, num;
int times[101][11];
for (int i = 0; i <= 100; i++) {
for (int j = 0; j <= 10; j++) {
times[i][j] = 111111111;
}
}
for (int i = 1; i <= 100; i++) {
times[i][1] = i;
}
for (int j = 1; j <= 10; j++) {
times[0][j] = 0;
}
for (int j = 1; j <= 10; j++) {
for (int i = 1; i <= 100; i++) {
for (int k = 1; k <= i; k++) {
times[i][j] = min(times[i][j], max(times[k-1][j-1], times[i-k][j]) + 1);
}
}
}
while (cin >> hardness >> num) {
cout << times[hardness][num] << endl;
}
return 0;
}
思维竟然有点混乱,确实需要复健啊!
Dynamic Programming,动态规划 ↩︎