[CSP-J2019] 纪念品
[CSP-J2019] 纪念品
知识点:完全背包
注意到,对于某件商品,我们可以当天卖出当天买回,于是我们在一天中对于某件商品,可以有以下的策略:
1、不买
2、买完后第二天卖掉
3、买完后过几天卖掉
对于策略3,我们可以将其转化为:当天买;然后第二天卖掉,第二天买回;然后第三天卖掉,第三天买回......
所以对于每件物品,我们可以只计算过一天的收益,如果一件物品需要经过多天才有收益,我们可以将其拆解为这些天的收益和。将总收益转化为每天的收益和即可。
于是我们拆成解决每天的收益即可。
我们尝试使用动态规划解决,定义 表示对于某一天,前 个物品,本金为 的时候的最大收益。于是我们的转移是这样的。
其中 表示第 天第 件商品的价格。
很显然,这是一个完全背包的转移,于是我们化简,回顾一下化简的过程
结合以上两个式子,得出
复杂度
#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;
}