CSP-J 2019 T3 纪念品
Posted zhuier-xquan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSP-J 2019 T3 纪念品相关的知识,希望对你有一定的参考价值。
(mathfrak{a}).反思:
通过这道题成功发现自己的背包还是很差(w);
可能这是我(gu)了好久好久博客的报应叭
就在做这个题的时候,自己连背包(dp)的思想都忘了
背包可以说是最早接触的(dp)了,还记得自己(CSP)之前他们讲背包,自己是真的忘记了。
可以说是在(dp)的洪流中忘本了吧
(mathfrak{b}. Solution):
其实是一个蛮显眼的多次完全背包问题,但思路受限于纪念品的卖出和买进。
第一想法是用一个数组(NT[])在更新的时候记录下每种物品的数量,乱七八糟状态爆炸(color{gold}{Boom!})。
题目中有一句话还是挺关键的:
“每天卖出纪念品换回的金币可以立即用于购买纪念品,当日购买的纪念品也可以当日卖出换回金币”
这也就提示我们可以当天买的纪念品在第二天卖出,如果并不打算在第二天卖出的话,显然我们可以把它再买回来((wonderful!)
然而我并没有那个敏感。
这样就省去了记录(NT[])数组的状态表达;
对每天做一次完全背包(day 1 o T),设(dp[j])表示当天恰好花费(j)元时获得的最大收益,把某件物品的价格看做体积,把这一天买入,第二天卖出的所收获的"差价"看做是价值,转移方程:
(dp[j]=max {dp[j-cost_{day,i}]+cost_{day+1,i}-cost_{day,i},j>=cost_{day,i}}),其中(cost_{a,b})表示第(a)天第(b)件物品的价格.
每天做完背包以后取最大的(dp[j]),更新下一天初始拥有的钱数(贪心的想:当我们某天拥有的钱数最多的时候,最终解最优)
(mathfrak{c}.Code:)
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int ans=0;
char last=' ',ch=getchar();
while(ch>'9'||ch<'0') last=ch,ch=getchar();
while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
if(last=='-') ans=-ans;
return ans;
}
int P[110][110];
int NT[110];
int dp[101000];
int main() {
int T,M,N;
T=read();
N=read();
M=read();
for(int i=1;i<=T;i++)
for(int j=1;j<=N;j++)
P[i][j]=read();
int MAxn;
for(int d=1;d<=T;d++) {
MAxn=-0x9f9f9f9;
dp[0]=M;
for(int i=1;i<=N;i++) {
for(int j=P[d][i];j<=M;j++)
dp[j]=max(dp[j],dp[j-P[d][i]]-P[d][i]+P[d+1][i]);
}
for(int j=0;j<=M;j++)
MAxn=max(MAxn,dp[j]);
M=MAxn;
}
printf("%d",M);
return 0;
}
双倍经验的快乐(s* lz把数组大小开反了然后快乐RE+WA P2938
以上是关于CSP-J 2019 T3 纪念品的主要内容,如果未能解决你的问题,请参考以下文章