题目大意:
有一个傻X无聊的公司用扔鸡蛋的办法测试鸡蛋硬度,求最坏情况要扔几次,只能从第一层扔到第n层,如果这个鸡蛋在第n层没碎,在n+1层碎了,这个鸡蛋的硬度就是n。然后多事的小A又想着用二分,结果想到自己都烦还在想。(无聊的小A)然后又让你帮他解决问题。
【输入】
输入包括多组数据,每组数据一行,包含两个正整数n和m(1≤n≤100,1≤m≤10),其中n表示楼的高度,m表示你现在拥有的鸡蛋个数,这些鸡蛋硬度相同(即它们从同样高的地方掉下来要么都摔碎要么都不碎),并且小于等于n。你可以假定硬度为x的鸡蛋从高度小于等于x的地方摔无论如何都不会碎(没摔碎的鸡蛋可以继续使用),而只要从比x高的地方扔必然会碎。
对每组输入数据,你可以假定鸡蛋的硬度在0至n之间,即在n+1层扔鸡蛋一定会碎。
【输出】
对于每一组输入,输出一个整数,表示使用最优策略在最坏情况下所需要的扔鸡蛋次数。
【输入样例】
100 1
100 2
【输出样例】
100
14
解题思路:
其实就是记忆化搜索
先要处理好边界问题吧:
if (m==1) return f[n][m]=n; //如果只有一个鸡蛋,那只能扔n次,不然直接碎了就没机会了。
if (m==0) return f[n][m]=0; //没有鸡蛋扔个皮皮虾
if (n==1) return f[n][m]=1; //只有一层楼还用说吗?就算这个鸡蛋的硬度是10^1000000,还是只能测出来是1。
if (n==0) return f[n][m]=0; //楼都没有扔个皮皮虾。
好了,边界处理好了
重点来了
你们最想要的动态转移方程
源程序奉上:
#include<cstdio>
#include<cstring>
#define inf 0x3f
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n,m,ans,f[101][101];
int max(int x,int y)
{
return x>y?x:y;//等于 if(x>y)return x;else return y;
}
int min(int x,int y)
{
return x>y?y:x;//等于 if(x>y)return y;else return x;
}
int dp(int n,int m)
{
if (f[n][m]<inf) return f[n][m];//如果找过了就退,不用重复再找(记忆化搜索)
if (m==1) return f[n][m]=n;
if (m==0) return f[n][m]=0;
if (n==1) return f[n][m]=1;
if (n==0) return f[n][m]=0;//这四条边界处理上面讲过了
r(i,1,n)
f[n][m]=min(f[n][m],1+max(dp(i-1,m-1),dp(n-i,m)));//在最坏情况下找最优解
return f[n][m];//返回
}
int main()
{
memset(f,inf,sizeof(f)); //赋初值,因为是找最坏情况中的最优解所以赋值很大
while (scanf("%d%d",&n,&m)==2)//读入
printf("%d\n",dp(n,m));//直接进入dp,输出返回值
}