tags
动态规划
中文题面
FTL
有两艘飞船,第 i i i 艘飞船( i ∈ [ 1 , 2 ] i∈[1,2] i∈[1,2])的攻击力为 p i p_i pi,每一次攻击的充能时间为 t i t_i ti,一开始两艘飞船没有充能。
现在要打败敌方飞船,敌方飞船的血量为 h h h,防御力为 s s s。对于一次攻击力为 P P P 的攻击,敌方飞船的血量会减少 ( P − s ) (P-s) (P−s)。每一次攻击可以是一艘飞船单独攻击,也可以是两艘飞船同时攻击(当一艘飞船完成充能后,可以等待另一艘飞船充能,然后再一起攻击)。两艘飞船一起攻击的攻击力为 p 1 + p 2 p_1+p_2 p1+p2。
打败敌方飞船的条件是使得敌方飞船的血量小于等于 0 0 0。现在依次给出 p 1 , t 1 , p 2 , t 2 , h , s p_1,t_1,p_2,t_2,h,s p1,t1,p2,t2,h,s,求出最少需要多少时间能够打败敌方飞船。
思路
考虑 d p dp dp,设 f i f_i fi 表示通过若干单发 + 最后恰好一次双炮连发使敌方耐久度减少 i i i 的最小时间, g i g_i gi 表示通过若干次若干单发 + 双炮连发的连续组合使敌方耐久度减少 i i i 的最小时间
代码
#include <iostream>
#define ll long long
using namespace std;
ll dp1[10007], dp2[10007];
int main(){
int p1, p2, h, s, n;
ll t1, t2, ans;
cin >> p1 >> t1 >> p2 >> t2 >> h >> s;
n = h + max(p1, p2);
ans = min(t1 * ((h - 1) / (p1 - s) + 1), t2 * ((h - 1) / (p2 - s) + 1));
for (int i = 1; i <= n; i++){
dp1[i] = dp2[i] = 4e18;
for (int j = 0; j * (p1 - s) + (p1 + p2 - s) <= i; j++){
ll x = i - (j * (p1 - s) + (p1 + p2 - s));
dp1[i] = min(dp1[i], max(t1 * (j + 1), t2 * ((x == 0 ? 0 : (x - 1) / (p2 - s) + 1) + 1)));
}
for (int j = 0; j < i; j++){
dp2[i] = min(dp2[i], dp2[j] + dp1[i - j]);
}
if (i >= h) ans = min(ans, dp2[i]);
}
cout << ans;
return 0;
}