一本通1300 鸡蛋的硬度
思路
首先你要看懂这个样例是什么意思,然后这个题就很简单了。其实就是一层楼一层楼的试,如果鸡蛋碎了,你就少了一个鸡蛋。如果没碎,那就从剩下的楼层再尝试。设\(f_{i,j}\)为手中还有\(i\)个鸡蛋,还有\(j\)层楼需要尝试的最多次数,那么转移就分两种情况进行讨论:\(1.\)如果碎了,那么就由\(f_{i-1,j-1}+1\)(你扔这一次还要算上一次)转移而来。\(2.\)如果没碎,那么就由\(f_{i,j-k}+1\)转移而来,其中\(k\)是枚举在那一层楼扔下去的。但是我们可以发现,如果直接三层循环,我们在枚举到\(f_{i,j}\)的时候可能不知道\(f_{i,j-k}\)的值,这样就没办法转移了。
于是,这时候就请出了记忆化搜索来完成这件事,再枚举一下边界情况,这个题就过了。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int n,m;
int f[110][110];
int dp(int i,int j){
if(f[i][j]<2147483647) return f[i][j];
if(i==1) return f[i][j]=j;
if(i==0) return f[i][j]=1000000000;
if(j==1) return f[i][j]=1;
if(j==0) return f[i][j]=0;
for(int k=1;k<=j;k++){
f[i][j]=min(f[i][j],max(dp(i-1,k-1),dp(i,j-k))+1);
}
return f[i][j];
}
int main()
{
while(cin>>m>>n){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
f[i][j]=2147483647;
}
}
printf("%d\n",dp(n,m));
}
return 0;
}