P5662 [CSP-J2019] 纪念品
你们可能会怀疑我为什么来写洛谷的题了。
那是因为那道题是DP训练里面的题……
P5662 [CSP-J2019] 纪念品
1.状态转移方程
关于DP最难的部分,当然是状态转移方程了。
-------------------------------------------
首先,出题人最干(sang)得(xin)漂(bing)亮(kuang)的地方就是:
在第n天买入,第m天卖出,
可以看成第n天买入,第n+1天卖出,第n+1天买入,第n+2天卖出……第m-1天买入,第m天卖出!(有反悔贪心的感觉吗)
反正又没限制能买多少次
那么炒股想盈利,当然是低买高卖了。
所以今天下午买了,明天价格高,明天上午就卖,如果后天的价格更高,明天下午买入,后天上午就卖!
所以可以得到:dp[i][j][k] = 第i天玩前j件物品,开始时k的现金,现在最多能得多少。
dp[i + 1][j][k] = max(dp[i][j][k], dp[i][j - 1][k - price[i][j]] + price[i + 1][j] - price[i][j])
原来的价格 买入之后原来的最大收益 明天的价格 - 今天的价格(获利)
2.用滚动数组压缩
第一维当然可以压了,毕竟只取最大嘛。
剩下的是完全背包,
第二维也可以压。
综上,此题做完了。
哎呀,忘放代码了。
#include <iostream> #include <string> #include <cmath> #include <cstdio> #include <cctype> #include <cstring> #include <iomanip> #include <cstdlib> #include <ctime> #include <set> #include <map> #include <utility> #include <queue> #include <vector> #include <bitset> #include <stack> #include <sstream> #include <algorithm> using namespace std; #define maxt 105 #define maxn 105 #define maxm 10005 int dp[maxm], price[maxt][maxn]; int main() { int T, N, M; scanf("%d %d %d", &T, &N, &M); for (int i = 0; i < T; i++) { for (int j = 0; j < N; j++) { scanf("%d", &price[i][j]); } } int ans = M; for (int i = 0; i < T - 1; i++) { memset(dp, 0, sizeof(dp)); for (int j = 0; j < N; j++) { for (int k = price[i][j]; k <= ans; k++) { dp[k] = max(dp[k], dp[k - price[i][j]] + price[i + 1][j] - price[i][j]); } } ans += dp[ans]; } printf("%d", ans); return 0; }