Solution - Stock Market G
Link。
一句话题意:求通过买卖股票能获得的最大钱数。
有一个转化(鬼知道怎么想到的):在第 \(i\) 天买股票然后在第 \(j\) 天卖出股票等价于在第 \(i\) 天买股票然后在第 \(i + 1\) 天卖出(\(k_1\) 只)股票,再在第 \(i + 1\) 天买(\(k_1\) 只)股票然后在第 \(i + 2\) 天卖出(\(k_2\) 只)股票,……,最后在第 \(j - 1\) 天买(\(k_{j - i}\) 只)股票然后在第 \(j\) 天卖出(\(k_{j - i}\) 只)股票。
通过这样巧妙的转化(确信),我们就可以把问题转化成相邻两天的买卖。于是我们就可以令 \(i\) 从第 \(1\) 天到第 \(d - 1\) 天循环,对邮票做完全背包,体积(买进,会消耗钱)是每只邮票第 \(i\) 天的价格,价值(卖出,会得到钱)是第 \(i + 1\) 天的价格,做完之后更新一下总钱数继续循环做即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 55, M = 105, K = 5e5 + 5;
int s, d, m, p[N][M];
int f[K];
int main() {
scanf("%d %d %d", &s, &d, &m);
for (int i = 1; i <= s; i++)
for (int j = 1; j <= d; j++)
scanf("%d", &p[i][j]); // p[i][j] 为第 i 只股票第 j 天的价格
for (int i = 1; i < d; i++) { // i 循环 [1, d)
for (int j = 0; j <= m; j++) f[j] = j; // 可以啥也不干,总钱数就是 j
for (int j = 1; j <= s; j++)
for (int k = p[j][i]; k <= m; k++)
f[k] = max(f[k], f[k - p[j][i]] + p[j][i + 1]); // 完全背包
m = f[m]; // 最后更新一下 m
}
printf("%d\n", m);
return 0;
}
所以这道题和 CSP-J2019 的纪念品有啥区别。
USACO 抄袭 CCF,退钱!!1
Posted by liuzimingc