【XDOJ】小W的塔防

原题:

小W在成功拿到iPhone后,下载了一个塔防游戏。游戏的目标是阻止僵尸穿过地图。

地图可以看作一条长度为n的线段,这条线段被划分为n条单位长度的小线段。僵尸需要花费t秒才能通过一条小线段。在每条小线段中,小W可以放置1个塔。塔有3种:

红色塔,每秒对正在通过塔的敌人造成x点伤害。

绿色塔,每秒对已经通过塔的敌人造成y点伤害。

蓝色塔,使已经通过塔的敌人减速,需要多花费z秒才能通过1单位长度。

“正在通过”定义为僵尸处于塔所在的单位长度小线段,“已经通过”定义为僵尸已经离开了这条小线段。

绿色塔、蓝色塔的效果可以叠加。换句话说,如果一个僵尸已经通过了a个绿色塔,b个蓝色塔,它将每秒受到来自绿色塔的ay点伤害,并且花费t+bz秒才能通过1单位长度。

小W希望知道,他至多可以给僵尸造成多少伤害。

1<=n<=100,0<=x,y,z<=60000,1<=t<=3

n很小,冰塔和毒塔的数量又不可能超过n

所以一眼f[i][j][k] n^3 DP,表示僵尸走到第i个线段,踩了j个毒塔,k个冰塔能吃掉的最大伤害

但是我没有1A,问题在哪里呢

一开始我是这样写的

1 for(int i=1;i<=n;++i)
2     for(int j=0;j<=i;++j)
3         for(int k=0;j+k<=i;++k){
4             f[i][j][k]=max(f[i][j][k],f[i-1][j][k]+(x+j*y)*(t+k*z));
5             if(j)  f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k]+(j-1)*y*(t+k*z));
6             if(k)  f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+j*y*(t+(k-1)*z));
7         }

然后f初值是0

结果样例没过,因为这样子有可能从f[0][1][0]转移到f[1][1][0]

然后我草率地把j<=i和j+k<=i改成j<i和j+k<i

显然这样是不对滴,注意j和k表示的是走过第i个线段时,踩了j个毒塔k个冰塔,之前的表述是不清楚的

喜闻乐见地WA了

正确改法应该是f初值全设-INF,f[0][0][0]设成0

突然想起来这个做法还是挺常见的,用来防止非法状态乱入

可能是退坑一年忘了吧哈哈

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 long long n,x,y,z,t;
 8 long long f[110][110][110];
 9 void rvs(){
10     for(int i=0;i<=n;++i)
11         for(int j=0;j<=n;++j)
12             for(int k=0;k<=n;++k)
13                 f[i][j][k]=-9999999999999999LL;
14     f[0][0][0]=0;
15     return ;
16 }
17 int main(){
18     //freopen("ddd.in","r",stdin);
19     while(scanf("%lld%lld%lld%lld%lld",&n,&x,&y,&z,&t)!=EOF){
20         rvs();
21         for(int i=1;i<=n;++i)
22             for(int j=0;j<=i;++j)
23                 for(int k=0;j+k<=i;++k){
24                     f[i][j][k]=max(f[i][j][k],f[i-1][j][k]+(x+j*y)*(t+k*z));
25                     if(j)  f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k]+(j-1)*y*(t+k*z));
26                     if(k)  f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+j*y*(t+(k-1)*z));
27                 }
28         long long ans=0;
29         for(int i=0;i<=n;++i)
30             for(int j=0;j<=n;++j)
31                 ans=max(ans,f[n][i][j]);
32         printf("%lld
",ans);
33     }
34     return 0;
35 }
View Code
原文地址:https://www.cnblogs.com/cdcq/p/11334991.html