zoukankan      html  css  js  c++  java
  • 洛谷P5662 纪念品(NOIp2019普及组T3)

    题目描述

    小伟突然获得一种超能力,他知道未来 (T)(N) 种纪念品每天的价格。某个纪念品的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量。

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

    任选一个纪念品,若手上有足够金币,以当日价格购买该纪念品;
    卖出持有的任意一个纪念品,以当日价格换回金币。
    每天卖出纪念品换回的金币可以立即用于购买纪念品,当日购买的纪念品也可以当日卖出换回金币。当然,一直持有纪念品也是可以的。

    (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
    

    输出 #1复制

    305
    

    输入 #2复制

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

    输出 #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 leq 4), (N leq 4), (M leq 100),所有价格 (10 leq P_{i,j} leq 100)

    另有 (15%) 的数据,(T leq 100), (N = 1)

    另有 (15%) 的数据,(T = 2, N leq 100)

    对于 (100%) 的数据,(T leq 100, N leq 100, M leq 10^3)
    ,所有价格 (1 leq P_{i,j} leq 10^4) ,数据保证任意时刻,小明手上的金币数不可能超过 (10^4)

    思路

    首先这很明显是一道dp
    作为只会dp的蒟蒻居然用了一天的时间也没想出来一道黄题,我太菜了。
    其实我只是没有想到一个事实:当天我卖掉的东西可以再当天买回来,所以我完全可以理解为每到新的一天我可以把手里所有的东西卖掉,如果我觉得不值,也就是以后卖我可能会赚钱,那我可以在今天再把卖掉的东西买回来,还是不亏的。其实想到这里我觉得这个题就一点也不难了,其实就是一个完全背包,再考虑一下状态转移方程就行了。其实认真(感性)理解一下就能发现,因为我们可以在新的一天将卖掉的东西原价买回来,所以我们买东西还是卖东西其实只跟明天的价格有关,那么我们的状态转移就是买不买和卖不卖东西。如果买了这个东西我们肯定要明天卖掉(大不了再买回来),不然就不买。用 (f_i) 表示手里还剩 (i) 元钱的时候能赚到的最多的钱是多少。那么状态转移方程就是 (f_k-a_{i,j}=max(f_k-a_{i,j},f_k+a_{i+1,j}-a_{i,j})(i)(j)表示第 (i) 个物品第 (j) 天的价格, (k) 表示当前手里有 (k) 元钱)。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    int t,n,m,ans;
    int f[10005];
    int a[110][110];
    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]);
    		}
    	}
    	ans=m;//第一天早上有m元 
    	for(int i=1;i<t;i++){//小于等于t也无所谓,因为最后一天肯定要都卖出去,不可能往里买,所以不会更新答案,但是准确来说应该是小于t 
    		memset(f,-0x3f,sizeof(f));//每一遍循环都要初始化 
    		f[ans]=ans;//如果我不买东西也不卖东西,那么手里有ans块钱最后也一定还剩ans块钱 
    		for(int j=1;j<=n;j++){
    			for(int k=ans;k>=a[i][j];k--){//类似于完全背包的思路,只要能买我可以一直买一样东西 
    				f[k-a[i][j]]=max(f[k-a[i][j]],f[k]+a[i+1][j]-a[i][j]);//状态转移方程 
    			}
    		}
    		int maxn=0;
    		for(int j=0;j<=ans;j++){
    			maxn=max(maxn,f[j]);//每次我都要看看手里最多能有多少钱 
    		}
    		ans=maxn;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    异步加载图片
    彩票项目
    linux 多线程的分离和可链接属性
    C库中system和atexit和exit的使用
    C库中getenv函数
    mode|平均数|方差|标准差|变异系数|四分位数|几何平均数|异众比率|偏态|峰态
    radar chart
    植物基因组|注释版本问题|重测序vs泛基因组
    signals function|KNN|SVM|average linkage|Complete linkage|single linkage
    supervised learning|unsupervised learning
  • 原文地址:https://www.cnblogs.com/57xmz/p/13360614.html
Copyright © 2011-2022 走看看