NC14553 小明打联盟(完全背包+贪心)
大意:
小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时间和固定的伤害值为:
1.乌鸦坐飞机 释放时间:x 固定伤害值:a
2.蜘蛛吃耳屎 释放时间:y 固定伤害值:b
3.饿狼前进 释放时间:z 固定伤害值:c
他还有一个大招,其释放的时间是一个区间【L,R】,可以在区间内任意时间点释放出技能,其如果在L+i时刻释放技能,其能够打出的伤害值为:temp+A*i
这里temp值表示技能的基础伤害(同时也就是在时刻L释放技能的伤害值),A是一个常数。
小明很喜欢研究连招使得在有限的时间内打出最高的伤害,现在他想要在T长度单位时间内打出最高的伤害,问这个最大伤害值。
思路:
可以想到利用完全背包,将大招化作R-L个物品,但是这样就变成n^2的复杂度,会超时
进一步考虑,因为大招的伤害是线性递增的,所以你要么选择不蓄力直接放,要么选择蓄满力再放,这样就把R-L个物品化成了2个物品
但是最后不一定能一直蓄满力再放大招,所以只需要最后枚举一下R-L长度的时间即可
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 5;
typedef long long LL;
LL T, x, a, y, b, z, c, L, R, temp, A, f[N];
struct node {
LL v, w;
};
vector<node> aa;
bool cmp(node a, node b) { return a.v < b.v; }
int main() {
while (cin >> T >> x >> a >> y >> b >> z >> c >> L >> R >> temp >> A) {
memset(f, 0, sizeof f);
aa.clear();
aa.push_back({x, a});
aa.push_back({y, b});
aa.push_back({z, c});
aa.push_back({L, temp});
aa.push_back({R, temp + A * (R - L)});
for (LL i = 0; i < aa.size(); i++) {
for (LL j = aa[i].v; j <= T; j++) {
f[j] = max(f[j], f[j - aa[i].v] + aa[i].w);
}
}
for (LL i = L; i <= R; i++)
f[T] = max(f[T], f[T - i] + temp + A * (i - L));
cout << f[T] << endl;
}
return 0;
}