pku2904: The Mailboxes Manufacturers Problem

pku2904: http://poj.org/problem?id=2904
题意:给k个油桶,要试验其能承受的爆炸底线,求对于最坏的情况(爆炸底线m最大)时需要试验的最少次数,比如k=1,m=10,则需从1开始试验,直到油桶爆炸,便可知起爆炸底线为该值-1,若为最坏情况,即为10,则要试验1+2+3……+10。若有2个油桶,可任意取一个值i试验,若油桶没有爆炸,则说明底线>i,否则<i且只剩一个油桶,需要从1开始试验(否则再炸了就没有油桶可以试验了) 解法:dp:dp[i][k][j]表示用第i个油桶从k到j试验的最优值,方程为dp[i][k][j]=min(dp[i][k][j],max(dp[i-1][k][t-1]+t,dp[i][t+1][j]+t))(k<=t<=j),表示如果油桶爆炸,则i-1,爆炸底线<t,所以k~t-1;如果不爆炸,则i,爆炸底线>t,所以t+1~j,(t已经确定不是了,所以不是t~j),因为是最坏情况,所以取最坏路径即max。
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
const int inf=1<<29;
int dp[20][150][150];
int min(int a,int b)
{
    if(a<b)
        return a;
    else
        return b;
}
int max(int a,int b)
{
    if(a>b)
        return a;
    else
        return b;
}
int main()
{
    int n,k,m;
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=100;i++)
    {
        for(int j=i;j<=100;j++)
        {
            dp[1][i][j]=(j-i+1)*(i+j)/2;
        }
    }
    for(int i=2;i<=10;i++)
    {
        for(int j=1;j<=100;j++)
        {
            for(int k=j;k>0;k--) //倒序枚举
            {
                dp[i][k][j]=inf;
                for(int t=k;t<=j;t++)
                {
                    dp[i][k][j]=min(dp[i][k][j],max(dp[i-1][k][t-1]+t,dp[i][t+1][j]+t));  //每个状态由从i-1(已算过)状态和[i][t+1][j](后面的状态)得到的,所以应先算后面的状态,即前面k倒序
                }
            }
        }
    }
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d",&k,&m);
        printf("%d\n",dp[k][1][m]);
    }
}
/*input:
4
1 10
1 100
3 73
5 100
output:
55
5050
382
495
*/

posted on 2012-07-25 14:24  acmer-jun  阅读(353)  评论(0编辑  收藏  举报

导航