Loading

:D 获取中...

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 @ 2022-07-21 15:08  liuzimingc  阅读(80)  评论(0编辑  收藏  举报