Loading

CF1743 E - FTL(线性DP)

E - FTL(线性DP)

题意

​ 现在你有两支激光枪,枪A伤害为\(p_1\),冷却时间为\(t_2\);枪B伤害为\(p_2\),冷却时间为\(t_2\)。敌人的护甲为s,可以抵消每一次攻击中的s点伤害。请问最快造成\(h(h \leqslant 5000)\)伤害的时间是多少。

思路

​ 如果将A和B一起发射,那么将造成\((p_1+p_2-s)\),对于单独的发射,为\(p_i-s\)。那么我们就知道,有时候需要单独发射,有时候需要齐射。易知这是一个动态规划问题。考虑到h比较小,可以设置状态\(f[i]\)为造成i点伤害花费的最小时间。

​ 第一步,我们可以得到一个简单的转移,也就是当前伤害为\(i\)是由上一次单独发射枪A或者枪B的而来的。但是这个情况就没有考虑到齐射的情况,我们现在就需要思考如何转移齐射的情况。枚举伤害是5e3,所以我们还可以通过\(O(n)\)的时间来枚举齐射。由于\(1 \leqslant t_i\),所以我们可以枚举一下让枪A射\(j\)轮,且最后一轮是齐射;以及让枪B射\(j\)轮,且最后一轮为齐射。那么转移方程就已经出来了,再初始化为正无穷,设\(f_0 = 0\),问题可解。

对于齐射的转移,我们可以看做在发动一次齐射之前,两者的策略就是:只要冷却时间一结束,就马上发起攻击。

实现

​ 我们会发现在前几个阶段递推的时候,下标会变负。假设我们的伤害都为5,那么\(f_1,f_2,f_3...\)这几个状态都是第一次独射得来的。所以我们直接将下标与0取一个max就可以了。

#define int long long
const int N = 5005;
int f[N];
int p1, p2, t1, t2;
int h, s;
 
void solve()
{
    cin >> p1 >> t1 >> p2 >> t2;
    cin >> h >> s;
    
    memset(f, 0x3f, sizeof f);
    f[0] = 0;
    for(int i = 1; i <= h; i ++)
    {
        f[i] = min(f[max(0ll, i - (p1 - s))] + t1, f[max(0ll, i - (p2 - s))] + t2);
        for(int j = 1; j <= i; j ++)
        {
            if(t1 * j >= t2)
            {
                int dmg = (j - 1) * (p1 - s) + (t1 * j - t2) / t2 * (p2 - s) + (p1 + p2 - s);
                f[i] = min(f[i], f[max(0ll, i - dmg)] + t1 * j);
            }
            if(t2 * j >= t1)
            {
                int dmg = (j - 1) * (p2 - s) + (t2 * j - t1) / t1 * (p1 - s) + (p1 + p2 - s);
                f[i] = min(f[i], f[max(0ll, i - dmg)] + t2 * j);
            }
        }
    }
    cout << f[h] << '\n';
}
posted @ 2022-10-19 17:02  DM11  阅读(78)  评论(0编辑  收藏  举报