题意:让你走进一个建筑扔鸡蛋,测试鸡蛋的硬度,即求出在哪层扔开始碎。进入建筑需要花费y元(不带鸡蛋),花费z元(带鸡蛋),在建筑里买鸡蛋需要花费x元。
开始一直没搞清楚题意,第一组和第二组样例出的时候,都是根据二分的思想来做的,不过对于后面的样例就不适用了。在看了xl的代码后,想到要枚举最后一次测试的层数,并且利用动态规划来搞。
f[i]表示要执行i次的最坏情况的最小花费,注意这里考虑的是从外面走进建筑的费用。
通过枚举最后一次测试的层数:
第一层和最后一层:
f[i-1]+z (通过测试1-(i-1)层,最后一次没碎则要测试第i层)
f[i-1]+x+y(测试2-(i)层,最后一次一次碎了则要测试第1层)
其他层可以有两种方式过来:
左边:f[j-1]+z
右边:f[i-j]+x+y
2<=j<=i-1
这题和上次那题差不多,通过枚举最后一个元素的情况来进行状态转移。
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 1005
#define INF 0xfffffff
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,s,t) for(int i=s;i<=t;i++)
#define ull unsigned long long
#define ll long long
using namespace std;
int n,x,y,z;
int f[maxn];
int main()
{
int t,tt=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d%d",&n,&x,&y,&z);
int tmp;
f[0]=0,f[1]=x+y;
for(int i=2;i<n;i++)
{
f[i]=min(f[i-1]+z,f[i-1]+x+y);//第i-1次碎了测试第一层,没碎测试最后一层的最坏情况
for(int j=2;j<=i-1;j++)//最后一次测试其他层
{
tmp=max(f[j-1]+z,f[i-j]+x+y);
f[i]=min(tmp,f[i]);
}
}
printf("Case %d: %d\n",tt++,f[n-1]);
}
return 0;
}