zoukankan      html  css  js  c++  java
  • HDU 2191悼念512汶川大地震遇难同胞——珍惜如今,感恩生活(多重背包)

    HDU 2191悼念512汶川大地震遇难同胞——珍惜如今。感恩生活(多重背包)

    http://acm.hdu.edu.cn/showproblem.php?pid=2191

    题意:

           如果你有资金n元, 然后有m种大米, 每种大米价格为cost[i], 重量为val[i], 数量为num[i]. 如今问你用n元钱最多能买多重的大米?

    分析:

           本题是典型的多重背包问题.

           我们令dp[i][j]==x表示仅仅购买前i种大米, 且总费用<=j时能购买的大米最大重量为x.

           初始化: dp为全0.

           因为每种大米有数量num[i], 所以我们分以下两种情况做:

           cost[i]*num[i]>=n, 我们直接对该种大米做一次全然背包过程就可以.

           cost[i]*num[i]<n , 我们把num[i]个第i类大米看成以下k+1种物品:

           1个(i类物品)  2个 4个 2^(k-1)个 以及 num[i]-2^k+1个

           我们对上述k+1种新物品每一个都做一个01背包就可以覆盖我们可能对第i种物品做出的全部选择.

           终于所求: dp[m][n]的值.

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=4000+5;
    
    int n;//金额
    int m;//大米种类
    int cost[100+5];//价格
    int val[100+5]; //重量
    int num[100+5]; //数量
    int dp[maxn];
    
    //一次01背包
    void ZERO_ONE_PACK(int cost,int val)
    {
        for(int i=n;i>=cost;i--)
            dp[i] = max(dp[i], dp[i-cost]+val);
    }
    
    //一次全然背包
    void COMPLETE_PACK(int cost,int val)
    {
        for(int i=cost;i<=n;i++)
            dp[i] = max(dp[i], dp[i-cost]+val);
    }
    
    //一次多重背包
    void MULTIPLE_PACK(int cost,int val,int num)
    {
        if(cost*num>=n)
        {
            COMPLETE_PACK(cost,val);
            return;
        }
    
        int k=1;
        while(k<num)
        {
            ZERO_ONE_PACK(k*cost,k*val);
            num -=k;
            k*=2;
        }
        ZERO_ONE_PACK(num*cost,num*val);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            //读取输入
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)
                scanf("%d%d%d",&cost[i],&val[i],&num[i]);
    
            //初始化+递推
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=m;i++)
                MULTIPLE_PACK(cost[i],val[i],num[i]);
    
            //输出结果
            printf("%d
    ",dp[n]);
        }
        return 0;
    }
    

  • 相关阅读:
    JBoss+Ant实现EJB无状态会话bean实例
    Nginx简单介绍
    SVN版本号管理工具使用中常见的代码提交冲突问题的解决方法
    深入分析Java中的I/O类的特征及适用场合
    ZOJ 3689 Digging(贪心+dp)
    uva 10641 (来当雷锋的这回....)
    Java编程中“为了性能”尽量要做到的一些地方
    wikioi 1306 机智Trie树
    PE文件结构(三) 输入表
    初始化的数值(int、double等)(一)
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7261492.html
Copyright © 2011-2022 走看看