zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Android 6.0运行时权限第三方库的使用-----RxPermissions
    Android当下最流行的开源框架总结
    Android使用SVG小结
    Android框架之路——GreenDao3.2.2的使用
    15 个 Android 通用流行框架大全
    Android sqlite 使用框架
    Android数据库框架——GreenDao轻量级的对象关系映射框架,永久告别sqlite
    根据图片名字在drawable中得到图片
    Repeater控件最后一笔记录高亮显示
    MasterPage + UpdatePanel + FileUpload
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4739340.html
Copyright © 2011-2022 走看看