zoukankan      html  css  js  c++  java
  • 三种背包模板

    零一背包倒着搜,完全背包正着搜,多重背包二进制存转化成01背包。

    0-1背包

    对于每种物品只有取与不取两个选择。

    洛谷p1048

    //https://www.luogu.com.cn/problem/P1048
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int maxn = 205;
    
    int cost[maxn];
    int val[maxn];
    int dp[105][maxn];        //dp[i][j]  当背包容积为j时,放入i的物品所获得的最大价值
    
    int main()
    {
        int t,m;
        scanf("%d%d",&t,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&cost[i],&val[i]);
        }
        for(int i=0;i<m;i++)
        dp[0][i]=0;
        for(int i=1;i<=m;i++)
            for(int j=t;j>=0;j--)
            {
                if(j>=cost[i])        //背包容积可以放下当前物品
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-cost[i]]+val[i]);
                else                  //放不下
                dp[i][j]=dp[i-1][j];
            }
        printf("%d
    ",dp[m][t]);
        return 0;
    }
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int maxn = 205;
    
    int cost[maxn];
    int val[maxn];
    int dp[1005];        //dp[j]  当背包容积为j时,所获得的最大价值
    
    int main()
    {
        int t,m;
        scanf("%d%d",&t,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&cost[i],&val[i]);
        }
        for(int i=0;i<m;i++)
        dp[i]=0;
        for(int i=1;i<=m;i++)          //滚动数组,依次遍历每个物品
            for(int j=t;j>=cost[i];j--) //当j小于cost[i]时,直接沿用原来的值  与二维 else dp[i][j]=dp[i-1][j];对应
            {
                dp[j]=max(dp[j],dp[j-cost[i]]+val[i]);
            }
        printf("%d
    ",dp[t]);
        return 0;
    }
    

    完全背包

    每种物品可以取无限多个。(在大部分情况下,用贪心思想,选性价比最高的物品其实就是答案,大概80%)。

    洛谷p2871

    //https://www.luogu.com.cn/problem/P2871
    //因数据范围问题,此代码无法ac,贴在这只是帮助理解
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int maxn = 205;
    
    int cost[maxn];
    int val[maxn];
    int dp[105][maxn];        //dp[i][j]  当背包容积为j时,可放入i种物品,所获得的最大价值
    
    int main()
    {
        int t,m;
        scanf("%d%d",&t,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&cost[i],&val[i]);
        }
        for(int i=0;i<m;i++)
        dp[0][i]=0;
        for(int i=1;i<=m;i++)
            for(int j=0;j<=t;j++)
            { 
                if(j>=cost[i]) //背包可以再放一个i类型的物品
                dp[i][j]=max(dp[i-1][j],dp[i][j-cost[i]]+val[i]);
                else  
                dp[i][j]=dp[i-1][j];
            }
        printf("%d
    ",dp[m][t]);
        return 0;
    }
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int maxn = 10000;
    
    int cost[maxn];
    int val[maxn];
    int dp[100000];        //dp[i][j]  当背包容积为j时,放入i的物品所获得的最大价值
    
    int main()
    {
        int t,m;
        scanf("%d%d",&t,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&cost[i],&val[i]);
        }
        for(int i=0;i<m;i++)
        dp[0]=0;
        for(int i=1;i<=m;i++)
            for(int j=cost[i];j<=t;j++)
            {
                dp[j]=max(dp[j],dp[j-cost[i]]+val[i]); //当j小于cost[i]时,直接沿用原来的值
            }
        printf("%d
    ",dp[t]);
        return 0;
    }
    

    多重背包

    每种物品限定了数量。

    可以把每一个都看成不同类型的物品,这样就转化成0-1背包问题了。

    但是直接转换会导致复杂度飙升,可以利用2进制来优化。

    以19为例子 它可以拆分(1+2+4+8+3),其实就是(2^0 + 2^1 + 2^2 + 2^3 +3)

    按照上面的划分,可以把19个同类型的背包拆分成5种不同类型的背包,比一个一个拆分要好得多。

    洛谷p1776

    //https://www.luogu.com.cn/problem/P1776
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    const int maxn = 40005;
    
    int dp[maxn];
    int val[maxn<<2];
    int wei[maxn<<2];
    
    
    int main()
    {
        int n,mw;
        scanf("%d%d",&n,&mw); //种类  最大容积
        int v,w,m; //价值 重量 数量
        int cnt=1;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&v,&w,&m);
            for(int j=1;j<=m;j<<=1)   //二进制优化
            {
                val[cnt]=v*j; wei[cnt]=w*j;
                m-=j; cnt++;
            }
            if(m) 
            {
                val[cnt]=v*m; wei[cnt]=w*m,cnt++;
            }
        }
        //for(int i=0;i<maxn;i++) dp[i]=0;
        for(int i=1;i<=cnt-1;i++)  //变成0-1背包问题
            for(int j=mw;j>=wei[i];j--)
            dp[j]=max(dp[j],dp[j-wei[i]]+val[i]);
        printf("%d
    ",dp[mw]);
        return 0;
    }
    
  • 相关阅读:
    postman的几个问题
    服了这个所谓北大青鸟官方学员社区论坛
    Gatling实战(三)
    Gatling实战(二)
    Gatling实战(一)
    httplib和urllib2常用方法
    jmeter的新增函数说明
    windows版jmeter的body data如何用 作为“换行”
    linux下oracle服务启动关闭
    linux下ORACLE监听日志的正确删除步骤
  • 原文地址:https://www.cnblogs.com/chilkings/p/11988990.html
Copyright © 2011-2022 走看看