zoukankan      html  css  js  c++  java
  • ACM__01背包,完全背包,多重背包

    今天写题的时候碰到了一道完全背包题,可是没有看出来,乱写了一通,浪费了一个晚上,顺便复习一下背包的知识

    01背包

    每种物品只能选择一次或者不选,求背包容量内的最大价值

    先给出状态转移方程:

    f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);

    解释一下:f[i][j]表示的是前i个物品中,背包容量为j时,得到的最大价值;如果在容量为j时选择不放第i个物品,那么f[i][j]=f[i-1][j],f[i-1][j]表示前一个物品在容量j时的状态值;如果在容量为j时选择放第i个物品,那么f[i][j]=f[i-1][j-w[i]]+v[i],f[i-1][j-w[i]]+v[i]表示前一个物品得到的状态加上第i个物品的价值;自然而然,f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);

    下面是二维数组的代码,自己敲了一遍,加深印象

     1 #include<cstdio>
     2 int main()
     3 {
     4     int n,m,v[105],w[105],f[105][105];
     5     scanf("%d %d",&m,&n);
     6     for(int i=1;i<=n;i++)
     7         scanf("%d %d",&v[i],&w[i]);
     8     for(int i=1;i<=n;i++)
     9     {
    10         for(int j=1;j<=m;j++)
    11         {
    12             if(w[i]<=j)
    13             f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
    14             else
    15                 f[i][j]=f[i-1][j];
    16         }
    17     }
    18     printf("%d",f[n][m]);
    19     return 0;
    20 }

    还有一种是一维数组的方法,更能节省空间

     1 #include<cstdio>
     2 int main()
     3 {
     4     int n,m,v[105],w[105],f[105];
     5     scanf("%d %d",&m,&n);
     6     for(int i=1;i<=n;i++)
     7         scanf("%d %d",&v[i],&w[i]);
     8     for(int i=1;i<=n;i++)
     9     {
    10         for(int j=m;j>=1;j--)
    11         {
    12             if(w[i]<=j)
    13             f[j]=max(f[j],f[j-w[i]]+v[i]);
    14         }
    15     }
    16     printf("%d",f[m]);
    17     return 0;
    18 }

    里面第二个循环为什么要倒着来,遍历到第i个物品时,f[j]应该与第i-1个物品的状态比较,如果顺着来的话,f[j]则与第i个物品的状态进行了比较,这样会出事的;

    完全背包

    每种物品可以选无数次,求背包容量内的最大价值

    状态转移方程为:f[j]=max(f[j],f[j-w[i]]+v[i]);

    贴上代码:

     1 #include<cstdio>
     2 int main()
     3 {
     4     int n,m,v[105],w[105],f[105];
     5     scanf("%d %d",&m,&n);
     6     for(int i=1;i<=n;i++)
     7         scanf("%d %d",&v[i],&w[i]);
     8     for(int i=1;i<=n;i++)
     9     {
    10         for(int j=w[i];j<=m;j++)
    11         {
    12             f[j]=max(f[j],f[j-w[i]]+v[i]);
    13         }
    14     }
    15     printf("%d",f[m]);
    16     return 0;
    17 }

    多重背包

    每种物品能取有限次,求背包容量内的最大值

    多重背包问题化作01背包问题解决,如果价值为v的物品有x个,则化成x个价值为v的物品;

    #include<cstdio>
    int main()
    {
        int n,m,v[105],w[105],f[105];
        scanf("%d %d",&m,&n);
        for(int i=1; i<=n; i++)
            scanf("%d %d",&v[i],&w[i],&num[i]);
        int k=n+1;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<num[i]; j++)
            {
                v[k]=v[i];
                w[k]=w[i];
                k++;
            }
        }
        for(int i=1; i<k; i++)
        {
            for(int j=m; j>=1; j--)
            {
                if(w[i]<=j)
                    f[j]=max(f[j],f[j-w[i]]+v[i]);
            }
        }
        printf("%d",f[m]);
        return 0;
    }
    

      再贴上今天折腾了一晚上的题:http://acm.sdibt.edu.cn/JudgeOnline/problem.php?id=2340

    把数组改为全局变量竟然就A了,问了老谭,说这是,没有清零的原因,脑瓜子疼!

  • 相关阅读:
    ios7 苹果原生二维码扫描(和微信类似)
    ios7之后 根据UILabel的文字计算frame的方法
    [Luogu1944] 最长括号匹配
    [bzoj3916] friends
    [NOIp2006] 能量项链
    [NOIp2003] 加分二叉树
    [Luogu1353] 跑步Running
    [Luogu2214] Mooo Moo S
    [POJ2452] Sticks Problem
    [POJ2406] Power Strings
  • 原文地址:https://www.cnblogs.com/LLLAIH/p/9665750.html
Copyright © 2011-2022 走看看