zoukankan      html  css  js  c++  java
  • 01 背包问题和完全背包

    Problem Description

    一个旅行者有一个最多能用m公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn.若每种物品只有一件求旅行者能获得最大总价值。

    Input

    输入的第一行为T,表示测试数据的组数。对于每组测试数据的第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30),第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

    Output

    对于每组测试数据输出仅一行,一个数,表示最大总价值。

    Sample Input

    1
    10 4
    2 1
    3 3
    4 5
    7 9

    Sample Output

    12
    【代码】
    
    

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

    //判断和不判断的差别 
    /*12
    1       1       1       1       1       1       1       1       1       0
    4       4       4       4       4       4       3       3       1       0
    9       9       8       8       6       5       5       3       1       0
    12      10      9       9       6       5       5       3       1       0
    */
    /*
    14
    1       1       1       1       1       1       1       1       1       1
    4       4       4       4       4       4       4       3       3       3
    9       9       9       8       8       8       5       5       5       5
    14      14      14      9       9       9       9       9       9       9
    
    */

    //每一件物品的状态抉择为放还是不放 如果不放 前i件物品 不超过v的最大值就是前i-1件物品不超过v的最大值

    否则 放就是 前i-1物品放入 v-w[i]的最大值加上要放入的当前的价值

    优化 二维数组优化为一维数组 f[v]为重量不超过v的最大值

    【代码】

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int w[20],c[20],f[20][20];
    int main()
    {
        int m,n;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
        scanf("%d%d",&w[i],&c[i]);
        for(int i=1;i<=n;i++)
        {
            for(int v=m;v>0;v--)
            {
                if(w[i]<=v)//必须要判断 
                f[i][v]=max(f[i-1][v],f[i-1][v-w[i]]+c[i]);
                else
                f[i][v]=f[i-1][v];
            }
        }
        printf("%d",f[n][m]);
        return 0;
    }

     完全背包

    【代码】

    二维

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int w[20],f[20][20],c[30];
    int main()
    {
        int m,n;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
        scanf("%d%d",&w[i],&c[i]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(w[i]>j)
                f[i][j]=f[i-1][j];
                else
                if(f[i-1][j]>f[i-1][j-w[i]]+c[i])
                f[i][j]=f[i-1][j];
                else
                f[i][j]=f[i-1][j-w[i]]+c[i];
            }
        }
        printf("%d",f[n][m]);
        return 0;
    }

    一维

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int f[20],w[20],c[20];
    int main()
    {
        int m,n;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
        scanf("%d%d",&w[i],&c[i]);
        for(int i=1;i<=n;i++)
        {
            for(int j=w[i];j<=m;j++)
            {
                if(f[j]<f[j-w[i]]+c[i])
                f[j]=f[j-w[i]]+c[i];
            }
        }
        printf("%d",f[m]);
        return 0;
    }

    数据 其实没多大用这数据。。。。 

    12(二维)
    0       1       1       1       1       1       1       1       1       1
    0       1       3       3       4       4       4       4       4       4
    0       1       3       5       5       6       8       8       9       9
    0       1       3       5       5       6       9       9       10      12
      
    
    12(一维)
    0       1       3       5       5       6       9       10      10      12

    01背包和完全背包的区别是完全背包每种物品有无数件 所以每次决策就改变了 不在是取或不取 而是取几件、

    分析一下代码 发现两个代码很像 区别就是01背包体积循环是 v--1,而完全背包是1--v

    why?

    为什么01逆序 完全顺序

    先讲01如果顺序后会怎样呢?

    我们知道f[v]=max(f[v],f[v-w[i]]+c[i]);如果顺序1--v,因为f[v]是由f[v-w[i]]推过来的,如果顺序的话 f[v-w[i]]一定推完了 我们可能在f[v-w[i]]时就已经

    放入了i物品 ,所以你推的f[v]就拿了两件i物品了,所以01要逆推,,,反之,,拿好几件就是完全 顺推了。。。。

    我也刚懂。。。糊里糊涂的。。。自己好好想想吧QAQ

  • 相关阅读:
    Silverlight4 打印 生成文件过大解决
    清理 Visual Studio 工具箱 的冗杂控件(第三方控件卸载不完全)
    SQL2005SP4生成数据库脚本视图依赖顺序错误问题
    SQL Server 2005 企业版没有 Management Studio管理工具
    Excel Reader 轻量级
    开发托管ActiveX或第三方程序托管插件时调试问题解决方法
    Entity Framework 从数据库生成模型丢失数据库文档不完美解决方案
    今天写了个很蛋疼的sql语句
    WinForm 内嵌 Office 文档 解决方案测试(非DSOFRAME 纯C#代码,网上独一份)
    生产者、消费者问题之闹钟
  • 原文地址:https://www.cnblogs.com/zzyh/p/6736276.html
Copyright © 2011-2022 走看看