楼层丢鸡蛋问题
2017-06-07 23:18
155 查看
经典的动态规划问题,题设是这样的:
如果你有2颗鸡蛋,和一栋36层高的楼,现在你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该如何用最少的测试次数对于任何答案楼层都能够使问题得到解决。
如果你从某一层楼扔下鸡蛋,它没有碎,则这个鸡蛋你可以继续用
如果这个鸡蛋摔碎了,则你可以用来测试的鸡蛋减少一个
所有鸡蛋的质量相同(都会在同一楼层以上摔碎)
对于一个鸡蛋,如果其在楼层i扔下的时候摔碎了,对于任何不小于i的楼层,这个鸡蛋都会被摔碎
如果在楼层i扔下的时候没有摔碎,则对于任何不大于i的楼层,这颗鸡蛋也不会摔碎
从第1层扔下,鸡蛋不一定完好,从第36层扔下,鸡蛋也不一定会摔碎。
如果你有2颗鸡蛋,和一栋36层高的楼,现在你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该如何用最少的测试次数对于任何答案楼层都能够使问题得到解决。
如果你从某一层楼扔下鸡蛋,它没有碎,则这个鸡蛋你可以继续用
如果这个鸡蛋摔碎了,则你可以用来测试的鸡蛋减少一个
所有鸡蛋的质量相同(都会在同一楼层以上摔碎)
对于一个鸡蛋,如果其在楼层i扔下的时候摔碎了,对于任何不小于i的楼层,这个鸡蛋都会被摔碎
如果在楼层i扔下的时候没有摔碎,则对于任何不大于i的楼层,这颗鸡蛋也不会摔碎
从第1层扔下,鸡蛋不一定完好,从第36层扔下,鸡蛋也不一定会摔碎。
#include <bits/stdc++.h> //#include <ext/pb_ds/tree_policy.hpp> //#include <ext/pb_ds/assoc_container.hpp> //using namespace __gnu_pbds; using namespace std; #define pi acos(-1) #define endl '\n' #define me(x) memset(x,0,sizeof(x)); #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++) #define close() ios::sync_with_stdio(0); #define rand() srand(time(0)); typedef long long LL; typedef pair<int, int> pii; const int INF=0x3f3f3f3f; const LL LINF=0x3f3f3f3f3f3f3f3fLL; const int dx[]={-1,0,1,0,-1,-1,1,1}; const int dy[]={0,1,0,-1,1,-1,1,-1}; const int maxn=1e3+5; const int maxx=1e6+100; const double EPS=1e-9; const int MOD=1000000007; #define mod(x) ((x)%MOD); #define hack ofstream fout; template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);} template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);} template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));} template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));} //typedef tree<pt,null_type,less< pt >,rb_tree_tag,tree_order_statistics_node_update> rbtree; /*lch[root] = build(L1,p-1,L2+1,L2+cnt); rch[root] = build(p+1,R1,L2+cnt+1,R2);中前*/ /*lch[root] = build(L1,p-1,L2,L2+cnt-1); rch[root] = build(p+1,R1,L2+cnt,R2-1);中后*/ long long gcd(long long a , long long b){if(b==0) return a;a%=b;return gcd(b,a);} int dp[1010][1010];//dp[i][j] i代表鸡蛋数。 j代表层数 int main () { int i,j,k,m,n; memset(dp,0,sizeof(dp)); for(i=1;i<=maxn;i++) dp[1][i]=i;//一个鸡蛋必须走完所有层 for(j=2;j<=maxn;j++) for(k=1;k<=maxn;k++) { dp[j][k]=1+dp[j][k-1];//鸡蛋没碎上一层楼 for(i=2;i<=k;i++) dp[j][k]=min(dp[j][k],1+max(dp[j-1][i-1],dp[j][k-i])); //一个鸡蛋从第i层扔下,如果碎了,还剩j-1个鸡蛋, //为确定下面楼层中的安全位置,还需要f[j-1,i-1]次 } while(scanf("%d%d",&m,&n)!=EOF) printf("%d\n",dp[m] ); return 0; }