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

    题意:给出经费的最大值n,再给出   种类m和每种的袋数c、价格p、重量h,求能买大米的最大重量

    思路:每种物品有一个固定的次数上限。为多重背包问题。转换为01背包来做

    以下方法,均为转化为01背包来做

    思路1:物品不摊开,选取每一种时,进行讨论,(相当于竖着填背包v的一列,一列一列的填

    码1:kj

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[110];
    int main()
    {
        int i,j,k,tem;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        int num[110];//每种物品个数
        int tc,tv;//拆分时物品花费,价值
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&_v,&n);
            memset(dp,0,sizeof(dp));
    
            for(i=1; i<=n; ++i)scanf("%d%d%d",&c[i],&v[i],&num[i]);
            //////
            for(i=1; i<=n; ++i)
                for(k=_v; k>=c[i]; --k)
                    for(j=1; j<=num[i]&&j*c[i]<=k; ++j)//此处比01背包多了一层循环
                    {
                        tc=j*c[i];
                        tv=j*v[i];
                        tem=dp[k-tc]+tv;
                        if(tem>dp[k])dp[k]=tem;
                    }
            //
            printf("%d
    ",dp[_v]);
        }
        return 0;
    }
    View Code


    思路2:物品摊开,然后处理01背包(相当于横着填物品的一行,一行一行的填

    2.1朴素拆分,把每种物品展开,既有n件a物品,则进行n件是否选取操作

    码2:jk

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[110];
    int main()
    {
        int i,j,k,tem;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        int num[110];//每种物品个数
        int tc,tv;//拆分时物品花费,价值
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&_v,&n);
            memset(dp,0,sizeof(dp));
    
            for(i=1; i<=n; ++i)scanf("%d%d%d",&c[i],&v[i],&num[i]);
            //////
            for(i=1; i<=n; ++i)
                for(j=1; j<=num[i]&&j*c[i]<=_v; ++j)//此处比01背包多了一层循环
                    for(k=_v; k>=j*c[i]; --k)
                    {
                        tem=dp[k-c[i]]+v[i];
                        if(tem>dp[k])dp[k]=tem;
                    }
            //
            printf("%d
    ",dp[_v]);
        }
        return 0;
    }
    View Code


    hint:2.1代码与思路1 代码 只是循环次序不一样而已,实际是一样的操作。(并且时间复杂度相同,略麻烦。
    因为
    思路1:
    for(k=_v; k>=c[i]; --k)
          for(j=1; j<=num[i]&&j*c[i]<=k; ++j)
    思路2:
    for(j=1; j<=num[i]&&j*c[i]<=_v; ++j)
          for(k=_v; k>=j*c[i]; --k)

    大体看一下这俩循环,

    这两个循环做的循环次数是相同的,也就是说,计算次数相同,时间复杂度相同


    2.2  二进制拆分,有n件a物品,则拆成 1,2,4,8,...,q 这样,即 1+2+4+...+q=n

    码3:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[110];
    int main()
    {
        int i,j,k,tem;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        int num[110];//每种物品个数
        int tc,tv;//拆分时物品花费,价值
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&_v,&n);
            memset(dp,0,sizeof(dp));
    
            for(i=1; i<=n; ++i)scanf("%d%d%d",&c[i],&v[i],&num[i]);
            //////
            for(i=1; i<=n; ++i)
            {
                for(j=1; j<=num[i]; num[i]=num[i]-j,j=j*2)//此处比01背包多了一层循环
                {
                    tc=j*c[i];//拆分后物品花费
                    tv=j*v[i];//
                    for(k=_v; k>=tc; --k)
                    {
                        tem=dp[k-tc]+tv;
                        if(tem>dp[k])dp[k]=tem;
                    }
                }
                if(num[i]>0) //如果还有物品,num[i] 即相当于 1+2+4+...+q  中的 q
                {
                    tc=num[i]*c[i];
                    tv=num[i]*v[i];
                    for(k=_v; k>=tc; --k)
                    {
                        tem=dp[k-tc]+tv;
                        if(tem>dp[k])dp[k]=tem;
                    }
                }
            }
        //
            printf("%d
    ",dp[_v]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    如何去除电脑上软件图标的快捷键小箭头
    三维地图如何加载gltf数据代码
    实时获取三维地图相机角度,改变三维观赏角度
    完美解决win10家庭版本系统无法远程连接问题
    svn提交批量选中文件
    oracle sql developer 如何支持多个窗体,打开多张表,多个tab,同时查看多个数据表
    sqldevelper批量导出sql文件
    原生javascript与jquery的区别(持续记录)
    iframs里子,孙页面与父,爷页面,以及多层嵌套的iframe中,js变量,方法以及元素的互相获取,调用
    Eclipse如何将多行注释的星号去掉
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4739310.html
Copyright © 2011-2022 走看看