zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    hdu 6702 ^&^ 位运算
    hdu 6709 Fishing Master 贪心
    hdu 6704 K-th occurrence 二分 ST表 后缀数组 主席树
    hdu 1423 Greatest Common Increasing Subsequence 最长公共上升子序列 LCIS
    hdu 5909 Tree Cutting FWT
    luogu P1588 丢失的牛 宽搜
    luogu P1003 铺地毯
    luogu P1104 生日
    luogu P1094 纪念品分组
    luogu P1093 奖学金
  • 原文地址:https://www.cnblogs.com/quanjun/p/13610575.html
Copyright © 2011-2022 走看看