• DP练习题 植物大战僵尸 题解 动态规划+费用提前计算


    题目描述

    聪聪喜欢玩植物大战僵尸,在游戏里有一条水平道路,道路的一端是入口,另一端是房子。僵尸会从道路的入口一端向房子一端移动。这条道路刚好穿过 (N) 块连续的空地。初始时,僵尸通过每块空地的时间是 (T) 秒。玩家可以在这 (N) 个空地中种植植物以攻击经过的僵尸,每块空地中只能种植一种植物。

    共有三种不同类型的植物,分别是红草、蓝草和绿草,作用分别是攻击、减速以及下毒。每种植物只能在僵尸通过它所在空地的这段时间内攻击到僵尸。

    • 当僵尸经过一块红草所在的空地时,每秒钟生命值会减少 (R) 点;
    • 当僵尸从一块蓝草所在的空地走出之后,通过每块空地的时间延长 (B) 秒;
    • 当僵尸从一块绿草所在的空地走出之后,每秒钟会因中毒减少 (G) 点生命值。

    蓝草的减速效果和绿草的下毒效果是可以累加的。也就是说,

    • 僵尸通过 (n) 块蓝草所在的空地之后,它通过每块空地的时间会变成 (T+B imes n) 秒;
    • 僵尸通过 (n) 块绿草所在的空地之后,它每秒钟会因中毒失去 (G imes n) 点生命值。

    注:减速和中毒效果会一直持续下去。

    聪聪想知道:怎样在这 (N) 块空地里种植各种类型的植物,才能使通过的僵尸失去的生命值最大。输出这个最大值。

    输入格式

    一行,五个空格隔开的整数 (N)(R)(G)(B)(T)

    输出格式

    一行,一个整数,即通过的僵尸失去的最大的生命值。

    样例输入

    3 3 3 3 3
    

    样例输出

    45
    

    说明/提示

    输入保证 (N le 3000)(R,G,B,T) 均为不超过 (100) 的正整数。

    题解

    首先,(N) 块空地必须得都种上草,不然就浪费了。

    其次,造成伤害的只有红草,有持续效果的是蓝草和绿草,所以为了让伤害尽可能地高,肯定是蓝草和绿草放前面,后面是连续的红草。

    但是蓝草和绿草的放置顺序就没有办法直接确定了,所以我们可以定义状态 (f[i][j]),表示前 (i+j) 块草地中,有 (i) 块蓝草和 (j) 块绿草的情况下,僵尸所失去的最大生命值(不包括后面的红草所带来的杀伤值)。

    对于每一个状态 (f[i][j]),它只有可能从以下两种状态转化而来:

    1. (i+j-1) 块草坪中,有 (i) 块蓝草和 (j-1) 块绿草,第 (i+j) 块草坪种绿草,此时僵尸经过第 (i+j) 块草坪造成的伤害的损耗为 ((i imes B + T) imes G imes (j - 1))
    2. (i+j-1) 块草坪中,有 (i-1) 块蓝草和 (j) 块绿草,第 (i+j) 块草坪种蓝草,此时僵尸经过第 (i+j) 块草坪造成的伤害的损耗为 (((i-1) imes B + T) imes G imes j)

    所以

    [f[i][j] = max { f[i][j-1] + (i imes B + T) imes G imes (j - 1) , f[i-1][j] + ((i-1) imes B + T) imes G imes j } ]

    (i+j) 块草地中有 (i) 块种蓝草,(j) 块种绿草的情况下,对于剩余 (n-i-j) 块种红草的草坪来说:

    • 经过每块红草的时间都为 ((i imes B + T)
    • 经过每块红草收到的伤害是红草的物理伤害加上累积的毒伤 (R + j imes G)

    所以经过后 (n-i-j) 块草坪的总伤害为

    [(n-i-j) imes (i imes B + T) imes (R + j imes G) ]

    所以最终的答案为

    [max { f[i][j] + (n-i-j) imes (i imes B + T) imes (R + j imes G) } ]

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 3030;
    int n;
    long long R, G, B, T, f[maxn][maxn], ans;
    int main() {
        cin >> n >> R >> G >> B >> T;
        for (int i = 0; i <= n; i ++) {
            for (int j = 0; i+j <= n; j ++) {
                if (j) f[i][j] = max(f[i][j], f[i][j-1] + (i*B+T)*G*(j-1));
                if (i) f[i][j] = max(f[i][j], f[i-1][j] + ((i-1)*B+T)*G*j);
                ans = max(ans, f[i][j] + (n-i-j) * (i*B+T) * (R+j*G));
            }
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    c#之继承
    javascript post数据到WCF反馈json或者XML
    五:理解控件的运行机制(例:基于Control命名空间的简单控件)
    c#之委托和事件
    项目管理中的十一个原则
    Linq:基本语法group by, order by ,into(3)
    Linq:基本语法form ,select, where(2)
    PL/SQL学习笔记视图
    七:理解控件的运行机制(例:基于CompositeControl命名空间的控件)
    PL/SQL学习笔记常量变量及数据类型初步
  • 原文地址:https://www.cnblogs.com/quanjun/p/13610575.html
Copyright © 2020-2023  润新知