题目描述

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

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

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

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

  • 僵尸通过 \(n\) 块蓝草所在的空地之后,它通过每块空地的时间会变成 \(T+B \times n\) 秒;
  • 僵尸通过 \(n\) 块绿草所在的空地之后,它每秒钟会因中毒失去 \(G \times 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 \times B + T) \times G \times (j - 1)\);
  2. 前 \(i+j-1\) 块草坪中,有 \(i-1\) 块蓝草和 \(j\) 块绿草,第 \(i+j\) 块草坪种蓝草,此时僵尸经过第 \(i+j\) 块草坪造成的伤害的损耗为 \(((i-1) \times B + T) \times G \times j\)。

所以

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

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

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

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

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

所以最终的答案为

\[\max \{ f[i][j] + (n-i-j) \times (i \times B + T) \times (R + j \times 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;
}