• hdu 4508 湫湫系列故事——减肥记I(完全背包)


    题意:完全背包

    思路:完全背包

    可以直接转化为 多重背包,num[i]=_v/c[i];//转为多重背包
    然后运用 多重背包 3种解法如下
    码1:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[100010];
    int main()
    {
        int i,j,k,tem;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        int num[110];//每种物品个数
        int tc,tv;//拆分时物品花费,价值
        while(~scanf("%d",&n))
        {
            memset(dp,0,sizeof(dp));
    
            for(i=1; i<=n; ++i)scanf("%d%d",&v[i],&c[i]);
            scanf("%d",&_v);
            for(i=1; i<=n; ++i)num[i]=_v/c[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:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[100010];
    int main()
    {
        int i,j,k,tem;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        int num[110];//每种物品个数
        int tc,tv;//拆分时物品花费,价值
        while(~scanf("%d",&n))
        {
            memset(dp,0,sizeof(dp));
    
            for(i=1; i<=n; ++i)scanf("%d%d",&v[i],&c[i]);
            scanf("%d",&_v);
            for(i=1; i<=n; ++i)num[i]=_v/c[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


    码3:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[100010];
    int main()
    {
        int i,j,k,tem;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        int num[110];//每种物品个数
        int tc,tv;//拆分时物品花费,价值
        while(~scanf("%d",&n))
        {
            memset(dp,0,sizeof(dp));
    
            for(i=1; i<=n; ++i)scanf("%d%d",&v[i],&c[i]);
            scanf("%d",&_v);
            for(i=1; i<=n; ++i)num[i]=_v/c[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


    另外:附一种更高效的方法 O(n*_v)
    与01背包代码中内层循环相反
    1...n
       0..._v

    码4:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[100010];
    int main()
    {
        int i,j;
        int t,n,_v;//测试用例个数,物品种类,背包大小
        int c[110],v[110];//花费,价值
        while(~scanf("%d",&n))
        {
            memset(dp,0,sizeof(dp));
            for(i=1; i<=n; ++i)scanf("%d%d",&v[i],&c[i]);
            scanf("%d",&_v);
            for(i=1; i<=n; ++i)
                    for(j=c[i];j<=_v;++j)
                        if(dp[j-c[i]]+v[i]>dp[j])dp[j]=dp[j-c[i]]+v[i];
            printf("%d
    ",dp[_v]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    spring boot 配置时区差别
    Java 中序列化与反序列化引发的思考?
    Http 状态码总结
    Springboot
    ConcurrentHashMap 实现缓存类
    C#基础(二)拆箱与装箱,循环与选择结构,枚举
    C#基础知识(一)自己总结的。。。
    贪吃蛇大作战双人版加强版完整代码加详细步骤,不懂问博主 啦啦啦。
    C#数组随机生成四个随机数
    C#添加背景音乐
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4739340.html
Copyright © 2020-2023  润新知