L - Coin Change-种类型完全背包

  • L - Coin Change

     UVA - 674 
  • 看完这个问题,你也许会觉得这个不就是01背包的升级版吗,其实就是这样,完全背包问题与01背包问题的区别在于完全背包每一件物品的数量都有无限个,而01背包每件物品数量只有1个
  • 所以说与它相关的策略已经不是只有取和不取这两种策略了,而是有取0件、取1件、取2件……等等很多种策略
  • 下面给出状态转移方程:

    f[i][j] = max{f[i][j],f[i-1][j - k * c[i]] + k * w[i]}(0<=k*c[i]<=v)

  • 我们现在dp每一个物品,dp出该种物品在不同剩余容量下的最优解,他是以每1个为单位的。考虑是否在当前所有物品总数中添加一件新的该物品

    我们用i代表前i种物品,v代表包的最大承重,c[i]是第i种物品消耗的空间、w[i]是第i种物品的价值、f[i,j]是最大价值(从前i种物品取若干件放入有j个剩余空间的包)。

    如果不放那么f[i][j]=f[i-1][j]

    如果确定放,那么f[i][j]=f[i][j-c[i]+w[i]]

  • 因为第i种物品一旦出现,原来没有第i种物品的情况下可能有一个最优解,现在第i种物品 出现了,而它的加入有可能得到更优解,所以之前的状态需要进行改变,故需要正序。

  • for (int i = 1; i <= n; ++i) 
    
        for (int j = w[i]; j <= v; ++j) 
    
            f[j] = max(f[j], f[j - c[i]] + v[i]);
    #include <cstdio>
    #include <cstring>
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 7500;
    int val[5] = {1,5,10,25,50};
    int n;
    int dp[N];
    int main()
    {
        while (cin>>n)
        {
            memset(dp, 0, sizeof(dp));
            dp[0] = 1;
            for (int i = 0; i < 5; i++)
                for (int j = val[i];j <= n; j++)
                    dp[j] += dp[j - val[i]];
            printf("%d\n", dp[n]);
        }
        return 0;
    }

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值