http://acm.timus.ru/problem.aspx?space=1&num=1223
DP 神一般的维度转换
最简单的想法就是 dp[ i ][ j ] i 个蛋 j 层楼 最少需要多少次试验
如果只有一个 蛋 则需要试验 j 次 否则:
dp[ i ][ j ] =min( dp[ i ][ j ] , max ( dp[ i ][ j-w] , dp[ i-1] [ w-1]) ) ; ( w<=j&&w>=1 ) (w 表示开始选择哪个楼层)
虽然这样很好理解 但是 需要枚举 w 所以时间复杂度可以达到 1000^3 太高
我们可以想象 在蛋的个数确定的情况下 一定的楼层数对应的最少试验次数 的求解
可以等同于 在蛋的个数确定的情况下 一定的试验次数对应的可以达到的最高楼层 问题的求解
ans[ i ][ j ] 表示 i 个蛋 j 次 试验最多可以测试的楼层数
这时我们就不需要枚举开始时测试哪个楼层了 因为
假设我们开始需要选择 第w个楼层才最优 则它下面有 ans[ i-1 ][ j-1] 个楼层 上面有ans[ i ][ j-1 ]个楼层
ans[ i ][ j ]=ans[ i-1 ][ j-1] + ans[ i ][ j-1 ] + 1;
并不要问选择了哪个楼层 其实 w 的值是可以通过 ans[ i ][ j-1 ] 来确定的 只不过没有必要而已
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> #define LL long long //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int N=1005; int ans[N][N]; int main() { //freopen("data.txt","r",stdin); for(int i=1;i<N;++i) ans[1][i]=i; for(int i=2;i<N;++i) { for(int j=1;j<N;++j) { ans[i][j]=ans[i-1][j-1]+ans[i][j-1]+1; } } int n,m; while(scanf("%d %d",&n,&m)!=EOF) { if(!n&&!m) break; for(int i=1;i<N;++i) { if(ans[n][i]>=m) {printf("%d\n",i);break;} } } return 0; }