• HDU 2844 Coins 多重背包


    原题链接:点击此处

    解题思路:

    多重背包问题,不太理解,理解了再补充。

    网上博客的思路是:

    对于每个硬币而言:
     
    IF 价值×数量>=m
     
           THEN 取这个硬币的次数相当于无限制,可以考虑成完全背包
     
    ELSE
     
           THEN 考虑成0-1背包(二进制优化),就是把这个硬币的v和num组合出0-1背包可能出现的状态(可以去看背包九讲)
     
    (对于num,类似于编码。  当2^n <=num/2时:k = 2^n(n=012,……)表示状态,对应下来就是二进制的某一位数是1,然后还有一个状态就是k>num/2的时候啦,num+1-k,这样下来就可以用k来组合枚举出从1->num的所有可能了。然后对于k,单位价值和大小都乘上k之后就变成了一个0-1背包)
    View Code

    源代码如下:

    #include <stdio.h>  
    #include <algorithm>  
    #include <string.h>  
    using namespace std;  
      
    const int MAX=100000;  
    int dp[MAX];  
    int c[MAX],w[MAX];  
    int v;  
      
    void ZeroOnePack(int cost,int wei)//01  
    {  
        int i;  
        for(i = v;i>=cost;i--)  
        {  
            dp[i] = max(dp[i],dp[i-cost]+wei);  
        }  
    }  
      
    void CompletePack(int cost,int wei)//完全  
    {  
        int i;  
        for(i = cost;i<=v;i++)  
        {  
            dp[i] = max(dp[i],dp[i-cost]+wei);  
        }  
    }  
      
    void MultiplePack(int cost,int wei,int cnt)//多重  
    {  
        if(v<=cnt*cost)
        {  
            CompletePack(cost,wei);  
            return ;  
        }  
        else
        {  
            int k = 1;  
            while(k<=cnt)  
            {  
                ZeroOnePack(k*cost,k*wei);  
                cnt = cnt-k;  
                k = 2*k;  
            }  
            ZeroOnePack(cnt*cost,cnt*wei);  
        }  
    }  
      
    int main()  
    {  
        int n;  
        while(~scanf("%d%d",&n,&v),n+v)  
        {  
            int i;  
            for(i = 0;i<n;i++)  
            scanf("%d",&c[i]);  
            for(i = 0;i<n;i++)  
            scanf("%d",&w[i]);  
            memset(dp,0,sizeof(dp));  
            for(i = 0;i<n;i++)  
            {  
                MultiplePack(c[i],c[i],w[i]);  
            }  
            int sum = 0;  
            for(i = 1;i<=v;i++)  
            {  
                if(dp[i]==i)  
                {  
                    sum++;  
                }  
            }  
            printf("%d
    ",sum);  
        }  
        return 0;  
    }  
    View Code
  • 相关阅读:
    聚会
    Wannafly summer camp Day2
    HDU6627 equation
    2019牛客暑期多校D.Big Integer
    对主席树的理解以及使用
    2019牛客暑期多校训练营(第四场)C.sequence(单调栈+线段树)
    2019 Multi-University Training Contest 1
    浅谈序列自动机
    2019江西省程序设计竞赛
    拉格朗日插值的应用
  • 原文地址:https://www.cnblogs.com/gdvxfgv/p/5767516.html
Copyright © 2020-2023  润新知