纪念品 -2019 CCF CSP-J2

小伟突然获得一种超能力,他知道未来 TT 天 NN 种纪念品每天的价格。

某个纪念品的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量。

每天,小伟可以进行以下两种交易无限次

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

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

当然,一直持有纪念品也是可以的。

TT 天之后,小伟的超能力消失。

因此他一定会在第 TT 天卖出所有纪念品换回金币。

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

输入格式

第一行包含三个正整数 T,N,MT,N,M,相邻两数之间以一个空格分开,分别代表未来天数 TT,纪念品数量 NN,小伟现在拥有的金币数量 MM。

接下来 TT 行,每行包含 NN 个正整数,相邻两数之间以一个空格分隔。第 ii 行的 NN 个正整数分别为 Pi,1Pi,1,Pi,2Pi,2,……,Pi,NPi,N,其中 Pi,jPi,j 表示第 ii 天第 jj 种纪念品的价格。

扫描二维码关注公众号,回复: 9501256 查看本文章

输出格式

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

数据范围

对于 10%10% 的数据,T=1T=1。

对于 30%30% 的数据,T≤4,N≤4,M≤100T≤4,N≤4,M≤100,所有价格 10≤Pi,j≤10010≤Pi,j≤100。

对于 15%15% 的数据,T≤100,N=1T≤100,N=1。

对于 15%15% 的数据,T=2,N≤100T=2,N≤100。

对于 100%100% 的数据,T≤100,N≤100,M≤103T≤100,N≤100,M≤103,所有价格 1≤Pi,j≤1041≤Pi,j≤104,数据保证任意时刻,小明手上的金币数不可能超过 104104。

输入样例1:

6 1 100
50
20
25
20
25
50

输出样例1:

305

输入样例2:

3 3 100
10 20 15
15 17 13
15 25 16

输出样例2:

217

样例解释

样例#1:
最佳策略是:

第二天花光所有 100100 枚金币买入 55 个纪念品 11;

第三天卖出 55 个纪念品 11,获得金币 125125 枚;

第四天买入 66 个纪念品 11,剩余 55 枚金币;

第六天必须卖出所有纪念品换回 300300 枚金币,第四天剩余 55 枚金币,共 305305 枚金币。

超能力消失后,小伟最多拥有 305305 枚金币。

样例#2:
最佳策略是:

第一天花光所有金币买入 1010 个纪念品 11;

第二天卖出全部纪念品 11 得到 150150 枚金币并买入 88 个纪念品 22 和 11 个纪念品 33,剩余 11 枚金币;

第三天必须卖出所有纪念品换回 216216 枚金币,第二天剩余 11 枚金币,共 217217 枚金币。

超能力消失后,小伟最多拥有 217217 枚金币。

思路:思路就是没有思路,本人不会dp,所以看了看题解, 懂了, 所以写了这个博客为其他不会的oier或acmer解答谜团

首先:这道题是贪心+dp(完全背包),贪心咋想的,dp一般有很多模型,结的多了做题时回想一下自己做过的模型题就会知道了,万变不离其宗,另外讲讲如何贪心, 为啥呀? 你要理解这个举例公式f[4] - f[1]= f[4]-f[3]+f[3]-f[2]+f[2]-f[1],理解了这个公式,你就知道我求f[4]-f[3] , f[3] - f[2], f[2]-f[1] 之和最大, 即 我求前面每个的最大之和就是所有的最大, 所以第一层循环理解了, for(1- t-1) , 里面套完全背包板子 , price[i][j]是容量,price[i+1][j]-price[i][j]是价值套就行, 更新m的容量即可

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 10090;
const int maxm = 100009;
int p[maxn][maxn];
int f[maxm];
int main() {
	int t;
	scanf("%d", &t);
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 1;i <= t;++i) {
		for(int j = 1;j <= n;++j) {
			scanf("%d", &p[i][j]);
		}
	}
	for(int i = 1;i < t;++i) {
		memset(f , 0, sizeof f);
		for(int j = 1;j <= n;++j) {
			for(int k = p[i][j];k <= m;++k) {
				if(p[i][j] < p[i+1][j]) {
					f[k] = max(f[k], f[k - p[i][j]] + p[i+1][j] - p[i][j]);
				}
			}
		}
		m += f[m];
	}
	printf("%d\n", m);
	return 0;
} 

  

发布了219 篇原创文章 · 获赞 43 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_43568078/article/details/103483256