现在的位置: 首页 > 综合 > 正文

UVA 4996 Scientific Experiment

2013年10月02日 ⁄ 综合 ⁄ 共 1813字 ⁄ 字号 评论关闭

题目链接:http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2997

————————————————————————————————————————————————————

题目描述:(直接摘抄网上的原句)

一个评估蛋的硬度方法是测量蛋从多高摔下来会碎。现在佳佳想以楼层高度作为考量依据评估蛋的硬度。如果蛋从i楼上掉下来会碎,而i-1不会,那么蛋的硬度为i。高为n层的实验楼里面有蛋卖,一个X元。佳佳开始没有蛋,并且他只能随身携带一个蛋,不带蛋进楼需要Y元,带蛋需要Z元,做完试验之后如果还有一个蛋,可以卖掉得X/2元(卖蛋不需要进楼)。佳佳把鸡蛋扔出去后,会出楼检查蛋的情况。如果蛋扔下后没有碎掉,佳佳一定会把蛋捡起,然后进楼,如蛋碎掉了,佳佳就不会管它。
佳佳想知道在最糟糕的情况下,测出蛋的硬度最少需要花费多少钱。

——————————————————————————————————————————————————

题目思路:

此题一开始分析样例时,以为只会有三种策略:二分,从上向下,从下向上。

后来到7 2 2时不再成立了。因为以上三种策略只适用于极限情况。若xyz接近,则问题就不是那么简单了。

再仔细分析问题,可以发现可以把问题划分掉,用很优美的dp解决掉。

分析可发现, 从1..n-1和 2..n 层分别检测蛋的硬度,其最坏的结果值应该是一样的(假设两者最初都是不带蛋进入楼房)。也就是说,问题与具体是哪个楼层无关,而只与楼层总数有关系。

故设 dp[i] 为 待测楼层总数为 i (此时我们默认i层是最高层,蛋会碎),一开始不携带鸡蛋,且站在楼外面时,在最糟糕情况下检测出蛋硬度的最少花费。

当我们还有i层待测时,假设我们从j (j<i)层扔下来 ,若蛋碎了,那么还剩下 j层要检测(第j层变成最高楼层,默认是蛋会碎,符合dp[i]的定义),则从 dp[i] 转移来; 若蛋没碎,那么还剩下 i-j层要检测(第j层变成了第0层,默认是不碎的们依然符合dp[i]定义),但是由于此时蛋没碎, 还要把蛋带着进去,而dp[i]的定义是不带鸡蛋进去,那么就要从

dp[i-j] - (x+y)+z 转移来,即减掉不带蛋进楼且进楼买蛋的费用,加上带蛋进楼的费用。

即  dp[i]  = max(dp[j],
dp[i-j] - (x+y)+z
) (j<i) 。

另外,边界值。dp[1] 显然为0 。且 当 i-j 为1的时候,即到了n-1层 蛋还没碎的时候,显然我们知道硬度就是n-1,不需要检测了,那个没坏的蛋就可以卖掉了 ,此时变为  
dp[i]  = max(dp[j], -x/2) (j == i-1)。

这题的关键问题是要想明白,结果与你在哪个楼层无关,而是与待检测的楼层的数目有关。并搞清边界值。

——————————————————————————————————————————————————

源代码:

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <string>
#include <map>

using namespace std;
#define maxn 1010
#define INF 1000000000
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))

int dp[maxn];
int x = 0,y = 0,z = 0;

void solve(int n)
{
    int i = 0,j = 0;
    int ans = 0;

    dp[1] = 0;
    for(i = 2;i<=n;i++)
    {
        ans = INF;
        for(j = 1;j<i;j++)
        {
           int t1 = dp[j];
           int t2 = dp[i-j]-x-y+z;
           if(i-j == 1)
             t2 = -x/2;
           ans = min(ans,max(t1,t2));
        }
        dp[i] = ans + x + y;
    }
}

int main()
{
    int n = 0,k = 0,t = 0;

    scanf("%d",&t);
    for(k = 1;k<=t;k++)
    {
        scanf("%d%d%d%d",&n,&x,&y,&z);
        solve(n);
        printf("Case %d: %d\n",k,dp[n]);
    }

    return 0;
}

抱歉!评论已关闭.