[一本通]鸡蛋的硬度
题意:
测试一批鸡蛋的硬度,有\(m\)个鸡蛋能用,鸡蛋碎了就不能继续用了,没碎可以捡回来,现在已知鸡蛋的硬度在\([1,n]\)以内或者不会碎。求最坏情况下最小的检测次数。
题解:
这道题在学校ACM课程选拔的时候见过。当时以为是分块或者二分,结果是动态规划。现在回想起来是的,分块和二分目的是优化时间,而非求得最优解,要想最优解还得看贪心和动态规划啊。
知道是动态规划了就好解决了,重点是状态划分。
只有一个鸡蛋的时候,高度为\(n\)要测试\(n\)次。
有\(m\)个鸡蛋的时候,假如在高度\(k\)测试了一次。
如果鸡蛋碎了,接下来就是用\(m-1\)个鸡蛋测试\(k-1\)个高度。
如果鸡蛋没碎,接下来就是用\(m\)个鸡蛋测试\(n-k\)个高度。
最坏情况就是两个取最大值。
\(f[n][m]\)表示\(n\)高度下,有\(m\)个鸡蛋,最少测试几次。
\(f[n][m] = min(max(f[k-1][m-1], f[n-k][m])+1)\)
#include <bits/stdc++.h>
#define Mid ((l + r) >> 1)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
using namespace std;
int read(){
char c; int num, f = 1;
while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
return f * num;
}
int n, m, f[19][109];
signed main()
{
memset(f, 0x3f, sizeof(f));
for(int i = 1; i <= 100; i++) f[1][i] = i; f[1][0] = 0;
for(int i = 2; i <= 10; i++) {
f[i][1] = 1; f[i][0] = 0;
for(int j = 1; j <= 100; j++) {
for(int k = 1; k <= j; k++) {
f[i][j] = min(f[i][j], max(f[i - 1][k - 1], f[i][j - k]) + 1);
}
}
}
while(cin >> n >> m) cout << f[m][n] << endl;
return 0;
}