Balls poj3783(dp,最坏情况最优解)

poj3783 Balls

题意:

 有一些鸡蛋,我们现在想知道这些鸡蛋的硬度。然后现在有一座很高很高的大楼里,我们现在要在这座大楼上测试鸡蛋的硬度。每个鸡蛋的硬度相同,鸡蛋的硬度定义为:如果鸡蛋从第 m 层上掉下来没有破裂,而从第 m+1 层上掉下来就破裂了,那么这个鸡蛋的硬度就是 m 。某个鸡蛋如果在实验中破裂了就永远的损失了。我们现在有 n 个鸡蛋。那么在最坏情况下我们最少需要做多少次实验呢?

思路:

  这是一个很经典的dp问题,设dp[n,m]是第i层楼,有k个鸡蛋时找到符合条件的最少测试次数
则一个鸡蛋从第 i 层扔下,如果碎了,还剩 m−1 个鸡蛋,为确定下面楼层中的安全位置,还需要dp[i−1,m−1] 次(子问题);不碎的话,上面还有 n−i 层,还需要 dp[n−i,m]次(子问题,实体 n 层楼的上 n−i 层需要的最少判断次数和实体 n−i 层楼需要的最少判断次数其实是一样的)

这里因为是要找最坏情况的最优解
所以在遍历每层楼的时候,应该要选择每一层楼中两种情况的最大值,然后再去比较其中的最小值

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#define __int128 LL

using namespace std;

typedef long long ll;

const int mod = 1e9;
const int maxn = 1e3 + 5;
const int INF = 1e9 + 7;

int dp[maxn][60];//dp[i][j]:表示在 i 层楼 还有 j 个鸡蛋的最小判断次数

void DP(int n,int m)
{
    
    
    memset(dp,0,sizeof dp);
    //对于一个鸡蛋,只能一层一层的试
    for(int i = 1; i <= n; i++){
    
        
        dp[i][1] = i;
    }
    //对于只有一层,肯定有且仅有一次
    for(int i = 1; i <=m; i++){
    
    
        dp[1][i] = 1;
    }
    for(int i = 1; i <= n; i++){
    
    
        for(int j = 2; j <= m; j++){
    
    
            dp[i][j] = i;//初始最坏结果是i次
            for(int k = 1; k <= i; k++) dp[i][j] = min(dp[i][j] ,max(dp[k - 1][j - 1] + 1,dp[i - k][j] + 1));
        }
    }
}

int main()
{
    
    
    int t;
    cin>>t;
    while(t--){
    
    
        int op,n,m;
        cin>>op>>m>>n;
        DP(n,m);
        cout<<op<<' '<<dp[n][m]<<endl;
    }
    return 0;
}```

猜你喜欢

转载自blog.csdn.net/CUCUC1/article/details/109407814