ural1223 鹰蛋(dp优化)

xiaoxiao2021-02-28  127

题意:

有一堆共 M 个鹰蛋,一位教授想研究这些鹰蛋的坚硬度 E。他是通过不断 从一幢 N 层的楼上向下扔鹰蛋来确定 E 的。当鹰蛋从第 E 层楼及以下楼层落下 时是不会碎的,但从第(E+1)层楼及以上楼层向下落时会摔碎。如果鹰蛋未摔 碎,还可以继续使用;但如果鹰蛋全碎了却仍未确定E,这显然是一个失败的实 验。教授希望实验是成功的。 例如:若鹰蛋从第 1 层楼落下即摔碎,E=0;若鹰蛋从第N层楼落下仍未碎, E=N。 这里假设所有的鹰蛋都具有相同的坚硬度。给定鹰蛋个数 M 与楼层数 N。 要求最坏情况下确定E 所需要的最少次数。

tip:

dp[i][j]表示用 i 个蛋在 j 层楼上最坏情况下确定答案所需要的最少次数 若蛋在w层碎了,那么答案在w-1那些层里面,(w是二分来的,因为二分是理论上快的),fdp【i-1】,【w-1】+1 若没碎,答案在w到n的那些层里面,dp【i】【j-w】)+1 两个中取较大的值,因为是最坏条件下,所以这两种都可能发生的话选更不好的, 循环ijw O(n^3) 优化: 首先如果蛋很多,多到够二分,那么结果一定是二分的值 2. 如图可以看出best的位置是dp最优选择,所以二分找dp【i-1】【w】 = dp[i][j-w]的w值。。

#include <cstdio> #include <iostream> #include <cstring> #include <cmath> using namespace std; const int maxn = 1100; const int inf = 1e9+7; int dp[2][maxn]; int egg,n; void bi_Se(int f,int i,int j){ int l = 1 , r = j; while(l <= r){ int mid = (l+r)/2; if(dp[f^1][mid-1] > dp[f][j-mid]){ r = mid-1; dp[f][j] = min(dp[f][j],dp[f^1][mid-1]+1); } else if(dp[f^1][mid-1] == dp[f][j-mid]){ dp[f][j] = dp[f^1][mid-1]+1; return ; } else{ l = mid+1; dp[f][j] = min(dp[f][j],dp[f][j-mid]+1); } } } void sov(){ for(int i = 0; i <= n ; i++) dp[1][i] = i; int now = 1,pre =0; for(int i = 2; i <= egg ; i++){ swap(now,pre); dp[now][0] = 0; for(int j = 1; j <= n ; j++){ dp[now][j] = inf; bi_Se(now,i,j); } } printf("%d\n",dp[now][n]); } int main(){ while(~scanf("%d%d",&egg,&n) && (egg || n)){ int tmp = floor(log(n)/log(2)+1); if(egg >= tmp) printf("%d\n",tmp); else sov(); } }
转载请注明原文地址: https://www.6miu.com/read-18457.html

最新回复(0)