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 纪念品的主要内容,如果未能解决你的问题,请参考以下文章

CSP-J&S2019前颓废记

CSP-J/S2019试题选做

CSP-J&S2019初赛游记

csp-j/s是啥考试?

代码大全2中文纪念版与英文珍藏版区别

20190918 - 纪念