P5662 纪念品
https://www.luogu.com.cn/problem/P5662
题意
- 用m金币在t天内买卖n个纪念品 。求最多得到多少钱
- n个纪念品在t天内的价格是不一样的。用数组 w[i]/[j]表示
- 同时关键——当天可以买卖纪念品。都是同样的价格。
想法
- 完全背包+贪心
- **当天可以买卖纪念品。都是同样的价格 ** 这个很关键。
- 这样可以把第i买,第j天卖的问题转化 为:则等价于在第 i 天买入,第 i+1 天卖出,第 i+1 天再买入, …, 在第 j 天卖出。
- 因为当天不限制买卖次数,如果明天价格高,大不了我今天卖掉之后再买回来
- 举个例子:10 20 30 40 表示第i天纪念品的价格。我有100.按之前说:
- 第一天:全买 ,买10个
- 第二天:全卖,卖10得 200.发现第三天价格为30,有利可图。重新买回10个。
- 按照策略。到第五天。
- 那么好办。问题,假设第 i 天的钱数是 mi,那么第 i+1 天的钱数最多是多少呢?
- 就变成了完全背包]
- 背包容量是 mi;
- 每个股票都是一种物品,体积是第 i天买入的价格,价值在第 i 天买入第 i+1天卖出的收益;
- 每天可以进行无限次交易,因此每种物品都是可以用无限次;
- 就变成了完全背包]
- 剪枝:当发现明天的价格低于今年。也就没有差价可赚了的时候。选择不买。
//P5662 纪念品
//https://www.luogu.com.cn/problem/P5662
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110,maxm = 10010;
int t,n,m;
//w[i][j]为每天的纪念品价格,dp[i]有钱i,第二天能挣多少(也就是利润)
int w[maxn][maxn],dp[maxm];
int main(){
cin>>t>>n>>m;
for(int i=1; i<=t; i++)
{
for(int j=1; j<=n; j++)
{
cin>>w[i][j];
}
}
//t-1次操作。2天只能操作一次
for (int i = 1; i <t; ++i) {
memset(dp,0, sizeof(dp));
//完全背包模板
for (int j = 1; j <= n; ++j) {
if(w[i+1][j] > w[i][j])//剪枝,如果第二天卖这个东西没有差价,就不用卖
{
for (int k = w[i][j]; k <= m ; ++k) {
dp[k] = max(dp[k],dp[k-w[i][j]]+(w[i+1][j]-w[i][j]));
}
}
}
m+=dp[m];//资本不断积累,本金+利润
}
cout << m;
return 0;
}