[CSP-J2019] 纪念品

[CSP-J2019] 纪念品

知识点:完全背包

注意到,对于某件商品,我们可以当天卖出当天买回,于是我们在一天中对于某件商品,可以有以下的策略:

1、不买

2、买完后第二天卖掉

3、买完后过几天卖掉

对于策略3,我们可以将其转化为:当天买;然后第二天卖掉,第二天买回;然后第三天卖掉,第三天买回......

所以对于每件物品,我们可以只计算过一天的收益,如果一件物品需要经过多天才有收益,我们可以将其拆解为这些天的收益和。将总收益转化为每天的收益和即可。

于是我们拆成解决每天的收益即可。

我们尝试使用动态规划解决,定义 dp[j][k] 表示对于某一天,前 j 个物品,本金为 k 的时候的最大收益。于是我们的转移是这样的。

dp[j][k]=maxkvp[i][j]0(dp[j1][kp[i][j]v]+v(p[i+1][j]p[i][j]))

其中 p[i][j] 表示第 i 天第 j 件商品的价格。

很显然,这是一个完全背包的转移,于是我们化简,回顾一下化简的过程

dp[j][kp[i][j]]=maxkvp[i][j]0(dp[j1][kp[i][j]v]+(v1)(p[i+1][j]p[i][j]))

结合以上两个式子,得出

dp[j][k]=max(dp[j1][k],dp[j][kp[i][j]]+p[i+1][j]p[i][j])

复杂度 O(TNM)

#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int INF = 0x3f3f3f3f, N = 5e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    int s, d, m; cin >> d >> s >> m;
    vector<vector<int>> p(d + 1, vector<int>(s + 1));
    for (int i = 1; i <= d; i ++ ) {
        for (int j = 1; j <= s; j ++ ) {
            cin >> p[i][j];
        }
    }
    int ans = m;
    for (int i = 1; i < d; i ++ ) {
        vector<vector<int>> dp(2, vector<int>(N));
        int mx = 0;
        for (int j = 1; j <= s; j ++ ) {
            int v = j & 1;
            for (int x = 0; x <= ans; x ++ ) {
                dp[v][x] = dp[v ^ 1][x];
                if (x - p[i][j] >= 0)
                    dp[v][x] = max(dp[v][x], dp[v][x - p[i][j]] + p[i + 1][j] - p[i][j]);
                mx = max(mx, dp[v][x]);
            }
        }
        ans += mx;
    }
    cout << ans << endl;
}
signed main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(2);
    int _ = 1;
//    cin >> _;
    while (_ -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}
posted @   Time_Limit_Exceeded  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示