zoukankan      html  css  js  c++  java
  • 背包问题--动态规划

    背包问题

         0-1背包问题涉及最值的获取,普通的测试方法很难得到结果,需要采动态规划方法。公式如下:

       

    其中,c[i,w]表示在包含了i物品的情况下背包承重为w下背包的最大价值。如果物品i重量大于w,直接跳过;如果物品i重量小于w,分为两种情况:

       (1)i物品装入,则要判断剩余i-1个物品在重量为w-wi前提下最大价值+i物品本身价值;

       (2)i物品不装入,判断剩余i-1物品在质量为w下最大价值,这是解题的关键;

    题目描述:

    有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

    name weight value 1 2 3 4 5 6 7 8 9 10
    a 2 6 0 6 6 9 9 12 12 15 15 15
    b 2 3 0 3 3 6 6 9 9 9 10 11
    c 6 5 0 0 0 6 6 6 6 6 10 11
    d 5 4 0 0 0 6 6 6 6 6 10 10
    e 4 6 0 0 0 6 6 6 6 6 6 6

    表格生成过程是从下至上,从左到右的,d2含义:只有物品d时,有个承重为2的背包,那么这个背包的最大价值是0,因为d物品的重量是5.

    下面说说a8推理过程如下:表格来自:http://blog.csdn.net/mu399/article/details/7722810

       (1)由于物体a质量2<8,因此根据推导公式判断b8和 b6+6(value)二者取大值

      (2)由表可知,b8=9,b6=9, b6+6(value)=15,所以取值15;

    其它取值过程类似。

    代码实现如下:

       

     1 #include<iostream>
     2 using namespace std;
     3 int c[200][200];//前i个物品装入容量为j的背包中获得的最大价值
     4 int max(int a,int b)
     5 {
     6    if(a>=b)
     7        return a;
     8    else return b;
     9 }
    10 
    11 int KnapSack(int n,int w[],int v[],int x[],int C)//w 物品的重量 v物品的价值  x 物品的选取状态 C背包最大容量
    12 {
    13     int i,j;
    14     for(i=0;i<=n;i++)
    15         c[i][0]=0;
    16     for(j=0;j<=C;j++)
    17         c[0][j]=0;
    18     for(i=0;i<=n-1;i++)
    19         for(j=0;j<=C;j++)
    20             if(j<w[i])//i物品重量超过j
    21                c[i][j]=c[i-1][j];
    22             else
    23                 c[i][j]=max(c[i-1][j],c[i-1][j-w[i]]+v[i]);//不选用i物品和选用i物品之间选最大的
    24             j=C;
    25             for(i=n-1;i>=0;i--)
    26             {
    27               if(c[i][j]>c[i-1][j])//选用i物品
    28               {
    29                 x[i]=1;
    30                 j=j-w[i];
    31               }
    32             else
    33                 x[i]=0;
    34             }
    35        cout<<"the select ting:"<<endl;
    36             for(i=0;i<n;i++)
    37               cout<<x[i]<<" ";
    38              cout<<endl;
    39         return c[n-1][C];
    40 
    41 }
    42 
    43 int main()
    44 {
    45     int s;//获得的最大价值
    46     int w[15];//物品的重量
    47     int v[15];//物品的价值
    48     int x[15];//物品的选取状态
    49     int n,i;
    50     int C;//背包最大容量
    51     cout<<"enter the max weight:C=";
    52     cin>>C;
    53     cout<<"enter the number :n=";
    54     cin>>n;
    55    cout<<"enter the weight of n thing:";
    56     for(i=0;i<n;i++)
    57           cin>>w[i];
    58  cout<<"enter the value of n thing:";
    59     for(i=0;i<n;i++)
    60          cin>>v[i];
    61     s=KnapSack(n,w,v,x,C);
    62  cout<<"the max value:"<<s;
    63 return 0;
    64 
    65 }

      测试结果如下所示:

       

    总结

       背包问题关键在于动态规划,动态规划关键在于公式的理解与掌握,加上实践。

  • 相关阅读:
    生成token和获取token
    python异常处理
    获取文件路径
    批量导出和批量安装第三方模块
    python操作从数据库中获取数据的接口
    centos中开机时如何自启动samba服务器
    MSSQL 创建自定义异常
    MSSQL 生成拼音码
    MSSQL FOR MXL PATH 运用(转载)
    MSSQL旋转和反旋转的例子
  • 原文地址:https://www.cnblogs.com/zhanjxcom/p/5819981.html
Copyright © 2011-2022 走看看