• Buy the souvenirs---hdu2126(01背包输出方案数)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126

    有n个物品每个物品的价格是v[i],现在有m元钱问最多买多少种物品,并求出有多少种选择方法;

    如果将物品的价格看做容量,将它的件数1看做价值的话,那么用01背包就可以求的花费m钱所能买到的最大件数dp[m]。

    但是题目还要求方案数,因此很容易想到再建立一个数组f[j],存储j元钱能买dp[j]个物品的方案数。

    在求解01背包的过程中,要分两种情况讨论:
      

    设当前所选的物品为i
      1.   若选了物品i后,能买的件数比不选物品i的件数大,即dp[j-val[i]]>dp[j]
        那么更新dp[j],同时,f[j]的方案数即为f[j-val[i]]
        原因是:假设f[j-val[i]]的方案数为 AB AC 两种,那么在此情况下加个D,为ABD,ACD,仍为两种,所以f[j]=f[j-val[i]]即可
        当然,要注意f[j-val[i]]为0的情况,因此当它为0时,f[j]=1,1即为D

      2.   若选了物品i后,能买的件数比不选物品i的件数相同,即dp[j-val[i]]==dp[j]
        即原先不选第i个物品,所需要的方案数为f[j];而选了物品i的方案数为f[j-val[i]]。
        因此,总的方案数即为f[j]+f[j-val[i]]
        当然,这里也要注意f[j-val[i]]=0的情况,当它为0时,f[j]+=1,1即为D

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<iostream>
    using namespace std;
    #define N 550
    #define met(a, b) memset(a, b, sizeof(a))
    
    int dp[N], f[N], v[N], n, m;
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            met(dp, 0); met(f, 0); met(v, 0);
    
            scanf("%d %d", &n, &m);
            for(int i=1; i<=n; i++)
                scanf("%d", &v[i]);
    
            for(int i=1; i<=n; i++)
            {
                for(int j=m; j>=v[i]; j--)
                {
                    if(dp[j]<dp[j-v[i]]+1)///物品i要选,例如已有ab和ac两种选法加个d还是两种选法;
                    {
                        dp[j] = dp[j-v[i]] + 1;
                        if(!f[j-v[i]]) f[j] = 1;
                        else f[j] = f[j-v[i]];
                    }
                    else if(dp[j]==dp[j-v[i]]+1)
                    {
                        if(!f[j-v[i]]) f[j] += 1;
                        else f[j] += f[j-v[i]];
                    }
                }
            }
            if(!dp[m])printf("Sorry, you can't buy anything.
    ");
            else printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.
    ", f[m], dp[m]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java反射系七之动态代理
    java反射系列六之调用属性与方法
    java反射系列五之获取类的完整结构
    java反射系列四之创建运行时类的对象
    java反射系列三之类加载器
    java反射系列二
    java反射系列一
    数据类型
    类的加载、连接和初始化
    算法
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5025872.html
Copyright © 2020-2023  润新知