纪念品-2019CSP-J

纪念品

题目描述

小伟突然获得一种超能力,他知道未来 T 天 N 种纪念品每天的价格。某个纪念品 的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量。
 每天,小伟可以进行以下两种交易无限次: 

  1. 任选一个纪念品,若手上有足够金币,以当日价格购买该纪念品;
  2. 卖出持有的任意一个纪念品,以当日价格换回金币。

 每天卖出纪念品换回的金币可以立即用于购买纪念品,当日购买的纪念品也可以当日卖出换回金币。当然,一直持有纪念品也是可以的。 

T 天之后,小伟的超能力消失。因此他一定会在第 T 天卖出所有纪念品换回金币。 

小伟现在有 M 枚金币,他想要在超能力消失后拥有尽可能多的金币。 

输入

第一行包含三个正整数 T,N,M,相邻两数之间以一个空格分开,分别代表未来天数 T,纪念品数量 N,小伟现在拥有的金币数量 M。 
接下来 T 行,每行包含 N 个正整数,相邻两数之间以一个空格分隔。第i行的 N 个正整数分别为 P i,1 , P i,2 …… ,P i,N,其中 P i,j表示第i天第 j 种纪念品的价格。

输出

输出仅一行,包含一个正整数,表示小伟在超能力消失后最多能拥有的金币数量

样例输入

【输入样例1】
6 1 100 
50 
20 
25 
20 
25 
50
【输入样例2】
3 3 100 
10 20 15 
15 17 13 
15 25 16

样例输出

【输出样例1】
305
【输出样例2】
217

提示

【样例1说明】
最佳策略是:
第二天花光所有 100 枚金币买入 5 个纪念品 1;
第三天卖出 5 个纪念品 1,获得金币 125 枚;
第四天买入 6 个纪念品 1,剩余 5 枚金币;
第六天必须卖出所有纪念品换回 300 枚金币,第四天剩余 5 枚金币,共 305 枚金币。
超能力消失后,小伟最多拥有 305 枚金币
【样例2说明】
最佳策略是:
第一天花光所有金币买入 10 个纪念品 1;
第二天卖出全部纪念品 1 得到 150 枚金币并买入 8 个纪念品 2 和 1 个纪念品 3,剩 余 1 枚金币;
第三天必须卖出所有纪念品换回216 枚金币,第二天剩余1枚金币,共 217 枚金币。
超能力消失后,小伟最多拥有 217 枚金币。
对于 10% 的数据,T= 1。 
对于 30% 的数据,T≤4,N≤4,M≤100,所有价格 10≤P i,j ≤100。 
另有 15% 的数据,T≤100,N=1。 
另有 15% 的数据,T=2,N≤100。 
对于 100% 的数据,T≤100,N≤100,M≤10^3 ,所有价格 1≤P i,j ≤10 4,数据保证任意时刻,小明手上的金币数不可能超过10 4 。

题解:

如果第i天的第j种商品在i天买进,第i+1天卖出去能产生收益,即p[i+1][j]−p[i][j]>0,就应该购入并在下一天卖出,这样产生的收益一定是最大的

问题演变为今天买入哪些商品能在下一天获取最大利益
也就是背包问题

故在每一天都用一次背包转移出用手上所拥有的钱数能产生多少利益
设dp[k]表示用k枚金币能产生的最大利益,则dp[m]就是当天所赚的利益

Code:

#include
#define N 105
using namespace std;
int t,n,dp[10005],m,a[N][N];
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 = 1; i <= t; ++i) 
	{
	    memset(dp,0,sizeof(dp));
	    for(int j = 1; j <= n; ++j)  
	        for(int k = a[i][j]; k <= m; ++k)
	            dp[k] = max(dp[k],dp[k - a[i][j]] + a[i + 1][j] - a[i][j]);
	    m = max(dp[m] + m,m);
	}
	printf("%d\n",m);
	return 0;
} 

 

你可能感兴趣的:(纪念品-2019CSP-J)