题目背景
说“善有善报,恶有恶报,不是不报……”。 小FF一心只顾自己企业的壮大而没顾及自己的采矿业对Greed Island上生态环境的破坏, Greed Island的环境日益恶劣。 终于,岛上的蚂蚁们变异了,它们决定对小FF的矿区进行攻击,欲将岛上的人类驱逐出去……面对蚂蚁们的进攻, 人类节节败退。无奈之下, 小FF请来了全宇宙最强的防御系统制造商派来的工程机器人——SCV,希望能够阻挡蚂蚁的攻势。
题目描述
经过小FF的研究,他发现蚂蚁们每次都走同一条长度为n个单位的路线进攻, 且蚂蚁们的经过一个单位长度所需的时间为T秒。也就是说,只要小FF在条路线上布防且给蚂蚁造成沉痛伤害就能阻止蚂蚁的进军。
SCV擅长制造的防御塔有三种,分别是激光塔,放射塔和干扰塔, 他们可以在一个单位长度内修建一座防御塔。三种防御塔的作用如下:
激光塔: 使用高能激光,当蚂蚁从塔前经过时每秒对蚂蚁造成r点伤害。
放射塔: 释放放射性元素, 当蚂蚁经过这座塔后,每一秒受到g点伤害。
干扰塔: 干扰塔负责干扰蚂蚁们的信息素,使得蚂蚁在经过这座塔后,经过之后每一个单位长度的时间变成T+b。
当然, 放射塔和干扰塔的效果是可以叠加的, 也就是说如果敌人经过x座放射塔,那么敌人每秒钟会受到x*g点伤害; 同理,如果敌人经过y座干扰塔, 那么敌人经过一个单位长度的时间将变为T+y*b。
现在距离蚂蚁的下一轮进攻还有足够长的时间,你这个“NewBe_One”计划的首席工程师现在被任命为战略总参谋长, 因此你必须设计一个给蚂蚁们造成最大伤害的布塔方案。
输入
输入数据仅一行, 5个整数 n, r, g, b, T中间用一个空格隔开。 它们分别表示你可以布防的总长度, 激光塔的效果、 放射塔的效果和干扰塔的效果。
对于30%的数据: 1<=n<=20;
对于60%的数据: 1<=n<=1024;
0<=r, g, b<=65536;
0<=T<=3;
对于另外40%的数据:
1<=n<=400;
0<=r, g, b<=2^31-1;
0<=t<=1000.
输出
输出仅一个整数, 代表你的方案给敌人带来的最大伤害值。
输入样例
5 4 3 2 1
输出样例
82
分析
首先我们要搞清楚题意。
题目中给了我们三种塔:
激光塔:蚂蚁经过时每秒r点伤害
放射塔:蚂蚁经过后每秒g点伤害,效果可累加
干扰塔:蚂蚁经过后速度变为T + b,效果可累加
激光塔对于位置没有什么要求,而干扰塔和放射塔很明显是越靠前所造成的总伤害越高,而单纯的干扰塔并不能对蚂蚁造成伤害,所以最终的方案一定是以一堆放射塔,一堆干扰塔,一堆激光塔的形式存在。
想明白了这一点,我们来思考这道题怎么做。
那么接下来我们要做的就是枚举每种塔的数量,然后求出最大伤害值
我们考虑使用DP来实现这个过程。
因为三种塔的数量总和一定为n,所以我们只需要将状态设计成两维。
用dp[ i ][ j ]来表示放了i个干扰塔,j个放射塔对蚂蚁造成的伤害
那么状态转移方程就比较清晰了:
dp[i][j] = max(dp[i - 1][j] + g * j * b * k, dp[i][j - 1] + g * (t + i * b) * k);
其中g * j * b * k表示增加一座干扰塔增加的伤害,g * (t + i * b) * k)表示增加一座放射塔造成的伤害。
那么,最后的答案就很好求了
ans = max(dp[i][j] + r * (t + i * b) * k)
r * (t + i * b) * k)表示增加一座激光塔的伤害
这道题比较不和谐的一点是它需要写高精。。不过被本蒟蒻使用__int128和谐掉了QAQAQ。
代码(__int128)
#include<bits/stdc++.h>
using namespace std;
__int128 n, r, g, b, t, ans;
__int128 dp[1050][1050];
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
return x * f;
}
void print(__int128 x) {
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
int main() {
n = read(), r = read(), g = read(), b = read(), t = read();
for (int i = 1; i <= n; i++) {
dp[0][i] = dp[0][i - 1] + (n - i) * g * t;
}
for (int i = 1; i < n; i++) {
for (int j = 1, k; k = n - i - j; j++) {
dp[i][j] = max(dp[i - 1][j] + g * j * b * k, dp[i][j - 1] + g * (t + i * b) * k);
}
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n - i; j++) {
int k = n - i - j;
if (k < 0) continue;
ans = max(ans, dp[i][j] + r * (t + i * b) * k);
}
}
print(ans);
}
emmmmm后面我打个高精的贴上来吧。。今天休息。。