5662 纪念品

5662 纪念品

为啥没做过这个?
不知道,可能觉得很难吧
没关系,现在来做做
t天之后,小伟的超能力就会消失,他要在这t天之内卖出所有的纪念品
所以,很明显,这就是一个动态规划问题
但是状态呢,怎么玩状态?状态貌似在这个题目中很好突破也很变态
于是我们定义一个数组f[i][j][k]来记录第i天,考虑到第j个物品1,手里面还有第k元的时候,明天早上能卖掉的最大的金币数量,然后就类似于背包的思路了
我们用prise[i][j]表示第i天第j个物品的价格
那么方程式就是f[i][j][k]=max(f[i][j][k],f[i][j-1][k+prise[i][j]]+price[i+1][j]-price[i][j]),表示第j个物品如果要了,手里的现金就会少了price[i][j],但是期望明天早上的收益也多了price[i+1][j]-price[i][j],为何如此,因为这是差价
j循环一遍以后,在收益里面取最大值,变成明天的金币就好了

但是三个维度肯定会炸
所以,我们可以把i给省略压缩掉了

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 105;
//dp[k]表示手里剩k元,明天早上都卖了以后的钱数
//price[i][j]表示第i天第j件物品的价格
int dp[10005], price[MAXN][MAXN];
int main() 
{
    int t, n, m, ans;
    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]);
        }
    }
    ans=m;//手上现有m元
    for (int i=1;i<t;i++) 
    {
        //先把数组赋值为负无穷
        memset(dp, ~0x3f, sizeof(dp));
        //什么都不买
        dp[ans]=ans;
        for (int j=1;j<=n;j++) 
		{
            //手里有k元的时候,去推明天早上的钱
            for (int k = ans; k >= price[i][j]; --k)
			{
                //买这件物品 
                dp[k - price[i][j]] = max(dp[k - price[i][j]], dp[k] + price[i + 1][j] - price[i][j]);//买的价值,和不买的价值
            }
        }
        int ma = 0;
        for (int j=0;j<=ans;j++) 
		{
            ma=max(ma, dp[j]);
        }
        //继续比较,比较最大的 
        ans=ma;
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值