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;
}

 

 

 

posted on 2012-09-25 16:44  夜->  阅读(255)  评论(0编辑  收藏  举报