poj3783 扔鸡蛋

题目大意:给定n层楼,m个鸡蛋,求最坏的情况下需要最少进行多少次扔鸡蛋(从1楼往上走),使得鸡蛋刚好摔碎。

dp[i][j]:剩余i个鸡蛋在第j层楼进行的最少次数
初始化:
(1)dp[i][0]=0(在第0层楼还没扔);dp[i][1]=1(在第一楼不管碎不碎都只扔一次)
(2)dp[1][i]=i(只有一个鸡蛋,在第i楼肯定需要扔i次)
最坏的情况:在碎和不碎的情况下取最大值
碎了则判断dp[i-1][k-1],没碎则还剩上面的j-k层没有判断,问题转化:上面的j-k层和从地面开始数j-k层的实验次数一样,所以dp[i][j-k];
状态转移方程:dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k])+1); +1是当前扔的一次

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 55;
const int M = 1010;
int dp[N][M];//剩余i个鸡蛋在j层楼进行的最少次数
int n, m;

void init()
{
    memset(dp, 0x3f, sizeof(dp));
    for(int i = 1; i < N; ++i)
    {
        dp[i][0] = 0;
        dp[i][1] = 1;
    }
    for(int i = 1; i < M; ++i)
        dp[1][i] = i;
    for(int i = 2; i < N; ++i)
        for(int j = 2; j < M; ++j)
            for(int k = 1; k < j; ++k)//最坏情况的最少次数,碎和没碎两种情况取最大值
                dp[i][j] = min(dp[i][j], max(dp[i][j-k]+1, dp[i-1][k-1]+1));
}

int main()
{
    int t;
    scanf("%d", &t);
    init();
    while(t--)
    {
        int cas;
        scanf("%d %d %d", &cas, &n, &m);
        printf("%d %d\n", cas, dp[n][m]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/81266444