• 【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
  • 相关阅读:
    js中new的本质
    js中真伪数组转换
    2 DC电参数测试 (1)
    1 开短路测试
    2月书单 《编码隐匿在计算机软硬件背后的语言》 21-25章
    2月书单 《编码隐匿在计算机软硬件背后的语言》 17-20章
    时间的掌控
    数码管的秘密
    会眨眼的小灯
    点亮一盏灯
  • 原文地址:https://www.cnblogs.com/cdcq/p/11334991.html
Copyright © 2020-2023  润新知