首页 > 其他分享 >[刷题笔记] Luogu P5662 [CSP-J2019] 纪念品

[刷题笔记] Luogu P5662 [CSP-J2019] 纪念品

时间:2023-08-02 20:16:10浏览次数:41  
标签:P5662 件物品 int Luogu price 背包 价钱 卖出 J2019

Problem

Description

类似于炒股票,有买进有卖出,当天可以既买进又卖出无限次,现在有若干件物品,每件物品都有一个价格,每天每件物品的价格不一致,你初始有\(m\)元钱,想要通过若干次购进卖出的操作,使得\(T\)天后你手里的钱最多。要求:\(T\)天结束你手中的股票必须全部售出。

Solution

乍看题发现如果直接dp状态很多,我们先来看看部分分:

对于10%的数据,T=1

当我们只有一天时,无论怎么搞只能有\(m\)元,直接输出\(m\)即可。这十分属于送分。

接下来考虑正解。

发现题目没有突破口了,想要dp却无法设计状态。

有一个重要的性质:题目允许当天买进当天卖出,如果我们在第\(l\)天买进,在第\(r\)天卖出,那么如果我们中间在第\(l+1\)天买进,在第\(l+1\)天卖出,在第\(l+2\)天买进,在第\(l+2\)天卖出......是不是不会影响答案?

这是本题的一个重要突破口。

我们都假设在第一天买进,在第二天早上卖出,显然我们希望第二天早上卖出的钱更多,满足局部最优解。

到这里,我们发现这是一个完全背包问题,考虑将完全背包问题的方程转换到本题中。
令\(f_{i,j,k}\)表示在第\(i\)天的时候,枚举前\(j\)件物品,手中钱有\(k\)元时,第二天能卖出的最大价钱。

则满足:

\(f_{i,j,k}=max(f_{i,j,k},f_{i,j-1,k+price_{i,j}}-price_{i,j}+price_{i+1,j})\)

(\(price_{i,j}\)表示第\(i\)天时第\(j\)件物品的价钱)

解释一下:第\(j\)天若在第二天卖出的最大价钱,可以通过上一件物品的最大价钱(上一件物品手中有的钱为\(k+price_j\),因为本次购买需要消费\(price_{i,j}\)元,同时第二天卖出能获得\(price_{i+1,j}\)元。

是不是类似于完全背包!

但是这样交上去会MLE,既然和完全背包类似,那就像完全背包一样考虑优化状态,由于第\(i\)天只依赖于第\(i-1\)天,故砍掉这层状态。枚举前\(i\)件物品也可以通过按照顺序枚举控制,故只需要保存手中前有\(k\)元时的状态就可以了!(和完全背包类似的)

这样我们就只需要令\(f_k\)表示手中钱有\(k\)元时第二天能卖出的最大价钱就可以了,状态转移方程如下:

\(f_k=max(f_k,f_k-price_{i,j}+price_{i+1,j})\)

和完全背包同理,枚举价钱的时候需要从大到小枚举。这样也算是每次尝试更改本物品可以改变的最大价钱。

由于dp时每天是独立的,每天和每天之间有关联的只有每件物品的价钱和持有金币数。所以每天开始前\(f\)数组都应初始化为极小值。
每天结束后取\(f\)数组里的max即为第二天开始时手中持有的金币数。(肯定选一个最赚钱的呀

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 10010
#define INF 0x3f3f3f3f
using namespace std;
int f[N];
int price[N][N];
int t,n,m;
int ans = 0;
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",&price[i][j]);
	}
	int money = m; //初始化手中持有的金币数为m
	for(int i=1;i<=t;i++)
	{
	//	cout<<money<<endl;
		memset(f,-INF,sizeof(f)); //每天开始前初始化为极小值
		f[money] = money; //边界:什么都不买的时候第二天还是拥有这些钱
		for(int j=1;j<=n;j++) 
		{
			for(int k=money;k>=price[i][j];--k) //和完全背包同理,倒着搜
			{
				f[k-price[i][j]] = max(f[k-price[i][j]],f[k]-price[i][j]+price[i+1][j]); 
			}
		}
		int maxn = 0;
		for(int j=0;j<=money;j++) maxn = max(maxn,f[j]); //每天结束后的金币max即为第二天开始时持有的金币数
		money = maxn; 
	}
	cout<<money<<endl;
	return 0;
 } 

标签:P5662,件物品,int,Luogu,price,背包,价钱,卖出,J2019
From: https://www.cnblogs.com/SXqwq/p/17601622.html

相关文章

  • [刷题笔记] Luogu P1466 [USACO2.2] 集合 Subset Sums
    ProblemDescription有一个长度为\(n\)的数组为\(1-n\),求有多少种选择方案使得选择数之和等于序列和的一半Solution题面翻译成这样是不是就好做了?首先,序列和的一半我们可以计算出\(n\times(n+1)\div2\div2\),显然序列和的一半只有是整数才有解,如果不是整数直接输出0即可。......
  • 【题解】Luogu[P2296] [NOIP2014 提高组] 寻找道路
    Link很简单的一道图论题。要在一个有向图上找一条\(s\)到\(t\)的最短路,要求这条路径上的所有点都满足:该点的所有出边所连点都能到达终点\(t\)。看上去很乱,我们简单分解一下,先在所有点中找到与终点有路径的点集\(A\)进行标记,再再所有点中找到其所有出边所连点都被打上标......
  • [刷题笔记] Luogu P2340 [USACO03FALL] Cow Exhibition G
    ProblemSolution乍看可能没有思路。我们注意到本题是牵扯到一头奶牛选or不选的问题,非常自然地想到01背包。接下来我们就尝试将本题背景转换成01背包问题。我们可以将智商转换成容量,情商转换成价值。(当然反过来也可)然后就可以套用01背包板子了:\[f_{i,j}=min(f_{i-1,j},f_{i-1......
  • [刷题笔记] Luogu P1877 音量调节
    ProblemDescription共\(n\)次操作,每次操作有一个值\(a_i\),同时给定一个初始值\(start\),对于每次操作,可以将值\(k\)加或减\(a_i\)(\(k\)初始=\(start\)),求经过这\(n\)操作后\(k\)的最大值。Solution其实这是一个01背包的变形。这和01背包有何关系呢?回顾一下经典01背包:有......
  • 【题解】Luogu[P2420] 让我们异或吧
    Link看到是树,又多组询问,立马想到类似的求和问题,异或不好理解,我们想求和怎么做,维护\(dis_i\)表示\(i\)节点到根的权值和,那么对于\(u,v\)两点路径上的权值和就是\(dis_u+dis_v-2\timesdis_{\mathrm{lca}(u,v)}\),这是很经典的问题了。事实上刚才的求和我们可以转化一下,我们......
  • luogu P4069 [SDOI2016] 游戏 题解【李超树+树剖】
    目录题目描述解题思路code题目描述P4069[SDOI2016]游戏一棵树,树上有\(n\)个节点,最初每个节点上有\(1\)个数字:\(123456789123456789\)。有两种操作:\(\centerdot\)选择\(s,t\)两个节点,将路径上的每一个点都变多(\(1\)个变\(2\)个)数字:\(a\timesdis+b\),其中\(dis\)表示该节点......
  • luogu P3733 [HAOI2017] 八纵八横 题解【线段树分治+线性基+可撤销并查集+bitset】
    目录题目大意解题思路code题目大意题目链接给出一张\(n\)个点\(m\)条边的连通无向图,边带边权\(w_i\)。有以下三种操作,共\(q\)次:\(\centerdot\)在点\(x,y\)之间加入一条边权为\(w_i\)的边,如果这是第\(i\)个此种操作,则记这条新边为第\(i\)条。\(\centerdot\)将第\(k......
  • 【题解】Luogu[P4711] 「化学」相对分子质量
    Link一道简单的模拟题,评绿可能有点高了。因为没有括号嵌套,难度瞬间降了一个档次,我们直接对着化学式扫一遍即可。若扫到左括号,说明接下来都是在括号内的,我们标记一下。若扫到大写字母,说明出现了一个新的元素,那么我们就看后面是否有下标,若有则类似于快读的方式直接处理后面的数......
  • luogu P9474 [yLOI2022] 长安幻世绘 详细题解
    原题:P9474[yLOI2022]长安幻世绘看到很多大佬的题解直接讲了做法,本蒟蒻看得不是很懂,调了很久才把这题做出来,于是写了这篇比较详细的题解谈一下我做这题从头到尾的思路,希望对各位有帮助qwq。思路我们首先思考这样一个问题,如果已经知道最终答案对应的最大值和最小值,又不知道题......
  • luogu P3203 [HNOI2010] 弹飞绵羊 题解
    题目传送门:P3203[HNOI2010]弹飞绵羊题意\(n\)个数,满足\(i<a_i≤N+1\),\(m\)次下面两种操作修改一个数\(a_i\)从\(x\)开始跳,\(x=a_x\),几次能够跳出序列\(n\leq2*10^5,m<10^5\)分析数据范围比较大,单纯搜索模拟肯定会T,那么考虑每次让他跳一段就......