题目链接:luogu P2938
题目
尽管奶牛天生谨慎,它们仍然在住房抵押信贷市场中大受打击,现在它们准备在股市上碰碰运气。贝西有内部消息,她知道 只股票在今后 天内的价格。
假设在一开始,她筹集了 元钱,那么她该怎样操作才能赚到最多的钱呢?贝西在每天可以买卖多只股票,也可以多次买卖同一只股票,交易单位必须是整数,数量不限。举一个牛市的例子:
假设贝西有 元本金,股票价格如下:
股票 | 今天的价格 | 明天的价格 | 后天的价格 |
---|---|---|---|
最赚钱的做法是:今天买入 股 张,到明天把它卖掉并且买入 股 张,在后天卖掉 股,这样贝西就有 元了。
输入
第一行:三个整数 , 和 , ; ;
第二行到第 行:第 行有 个整数: 到 ,表示第 种股票在第一天到最后一天的售价,对所有数据, , 。
输出
单个整数:表示奶牛可以获得的最大钱数,保证这个数不会超过
样例输入
2 3 10
10 15 15
13 11 20
样例输出
24
思路
这道题就是一道揹包。
我们对于每一个股票,我们可以在每一天对它进行个操作的其中一个:
- 不买
- 买完明天卖
- 买完第天卖
然后我们可以发现,第三种操作可以转换成很多次第二种操作。比如,第一天买入第三天卖出其实等于第一天买入,第二天卖出,第二天又买入,第三天又卖出。
那么这样,就只有选和不选了。
然后我们知道股票可以买很多张的,所以这道题就是完全揹包了。
对于每两天的间隔,我们都做一次完全揹包(即做次揹包),求出最多钱的那一次,就是答案了。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#define rr register
using namespace std;
int t, n, m, a[51][11], f[500001];
int main() {
scanf("%d %d %d", &t, &n, &m);//输入
for (int i = 1; i <= t; i++)
for (int j = 1; j <= n; j++)
scanf("%d", &a[i][j]);//输入
for (int i = 2; i <= n; i++) {
memset(f, 0, sizeof(f));//初始化
int maxn = 0;
for (int j = 1; j <= t; j++) {
for (rr int k = a[j][i - 1]; k <= m; k++) {
f[k] = max(f[k], f[k - a[j][i - 1]] - a[j][i - 1] + a[j][i]);//动态转移方程
maxn = max(maxn, f[k]);//记录最大值
}
}
m += maxn;//现有的钱为之前的钱加上今天赚的钱
}
printf("%d", m);//输出
return 0;
}