CF922E Birds (DP)

CF922E Birds (DP)

题目传送门

题目大意(翻译)

在一个公园的小巷里有一排树,每棵树上都有一个巢。在 i 的第一个巢里有 ci 只鸟;要从这个巢穴召唤一只鸟,小鬼需要呆在这棵树下,这需要消耗他的法力点。然而,每召唤一只小鸟,小鬼的法力值就增加 B 点。小恶魔可以逐个召唤鸟,他可以从 0 到 ci 召唤 i 个巢中的任意数量的鸟。

最初小鬼站在第一棵树下,法力值为 W 点,他的法力值也等于 W 点。他只能向前移动,每次从一棵树移动到下一棵树时,他恢复 X 点法力值(但不能超过他当前的法力值)。只向前移动,恶魔能召唤的鸟的最大数量是多少?

思路分析:

如果我们考虑直接对每一棵树的每一种情况进行 dp 的话,会发现这个不可行,因为每一棵树的鸟的数量都一样,并且状态转移方程十分难写
所以我们换一种思路,用 dp[i][j] 来表示到第 i 棵树召唤了 j 只鸟剩的最大魔力,这样我们的状态转移方程就好写了,直接见代码吧(添加了注释)(太懒了)
(蒟蒻的第一篇题解,这题也是研究了别人的题解才做出来的,路过的道友们酌情观看QWQ)

#include<iostream>
#include<algorithm>
#include <vector>

using namespace std;

typedef long long ll;
int n, w, b, x;
// -- 初始化为-1表示没有取到过j只鸟
// 不能初始化为0是因为dp[j]=0可能是由于取了j只鸟后才变为0,所以j是我们应该考虑的答案
// -- 仔细观察dp的过程可以发现这里的dp数组可以去掉一个维度
vector<ll> dp(10010, -1);
ll c[1010], va[1010];
ll p[20];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    p[0] = 1;
// 用这个p数组可以快速的枚举出每一个数的每一种情况(具体见dp过程)
// 原理可以去问问ai,~~我也不太懂怎么来的
    for(int i = 1;i <= 15;i ++) p[i] = p[i - 1] * 2;

    cin >> n >> w >> b >> x;
    dp[0] = w;
    for(int i = 1;i <= n;i ++) cin >> c[i];
    for(int i = 1;i <= n;i ++) cin >> va[i];
    ll sm = 0;
    for(int i = 1;i <= n;i ++){
    // sm 表示当前有可能取到的最多的数量    
        sm += c[i];
        // 每走一步恢复,但不能超出限制
        for(int j = 0;j <= sm;j ++){
            if(dp[j] == -1) continue;
            dp[j] = min(dp[j] + x, 1LL * j * b + w);
        }
        for(int j = 0;j <= 14;j ++){
            if(c[i] >= p[j]){
                c[i] -= p[j];
        // 倒序枚举        
                for(int k = sm;k >= p[j];k --){
                    if(dp[k - p[j]] < p[j] * va[i]) continue;
                    dp[k] = max(dp[k], dp[k - p[j]] - p[j] * va[i]);
                }
            }else break;
        }
        if(c[i]){
            for(int j = sm;j >= c[i];j --){
                if(dp[j - c[i]] < c[i] * va[i]) continue;
                dp[j] = max(dp[j], dp[j - c[i]] - c[i] * va[i]);
            }
        }
    }
    for(int i = sm;i >= 0;i --){
        if(dp[i] >= 0){
            cout << i;
            break;
        }
    }
    return 0;
}
posted @ 2025-03-18 18:22  ter_rave  阅读(11)  评论(0)    收藏  举报