博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
0-1背包问题
阅读量:6242 次
发布时间:2019-06-22

本文共 2128 字,大约阅读时间需要 7 分钟。

一个问题可以用动态规划法求解的先决条件:

    1、最有子结构性质:当问题的最优解包含了其子问题的最优解时,成该问题具有最有子结构性质。

    2、重叠子问题:每次产生的子问题并不总是新问题,有些子问题被反复计算多次。

满足了以上两个条件的问题可以考虑用动态规划法求解,他是一种自底向上的递归算法。

问题描述:

   给定n种物品和一背包,物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品(物品不能分割),使得装入背包中物品的总价值最大?
抽象描述如下:
     x[n]:表示物品的选择,x[i]=1表示选择放进物品i到背包中。
          
 
问题分析:
   1.抽象之后背包问题转换为找到一个最优的数组,x1,x2,.....,xn的0-1序列。
   2.假设最优解的序列为x1,x2,.....,xn,能使背包容量C的总价值最大.
       如果,x1=1,则x2,...,xn是C-w1容量的背包的总价值依然是最大的序列;
       如果,x1=0,则x2,....,xn是C容量的背包的总价值依然是最大的序列。
      这就是我们所说的最优子结构性质。
   3.进一步分析:我们用m(i,j)表示为已经判断好了1:i-1的序列的背包最大价值,并且此时的背包剩余的容量为j,对物品i进行判断
    如果j>wi, 就只要做出选择wi和不选择wi情况下,哪种更能使背包的总价值更大:m(i,j)=max{ m(i+1,j),m(i+1,j-wi)+vi}(注意这是个递归式)
    如果j<wi:       m(i,j)=m(i+1,j)
    初始化:        m(n,j)=vn  (j>= wn);
                    m(n,j)=0   (0<=j< wn) 
                    m(0,C)=0    
    最终的结果:m(1,C)

   4.依次我们就得到了一个递归的表达式:

               
      
       5.如果单纯的从利用递归,重复计算了很多的值,耗费的时间是很大的,动态规划还需避免这种重复计算,怎样自顶向下或自底向上的计算呢?
     采用列表的方法就可以很好的分析设计自顶向下或自底向上的计算的算法了
举例分析:
         n=3,c=6,w={4,3,2} v={5,2,1}
         m[i][j]=max{ m[i+1][j], m[i+1][j-w[i]]+v[i] }
         列表如下:
          
     最左边箭头:我们计算的方向,从第3行开始向上计算法值。
    表中红色箭头是我们通过选择做出的结果:列如 m[2][3]=max{m[3][3],m[3][3-w[2]]+v[2]},我们最终选择了m[3][3-w[2]]+v[2]。
    整个问题的最优解保存在m[1][6]中。

参考链接:

// 0-1beibao.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include
using namespace std;struct shop{ int weight; int value;};#define num 3shop cargo[num+1] = { {0,0}, {1,6},{2,10},{3,12} };#define W 5 //背包容量int menoy[num+1][W + 1];int max(int i, int j){ return i > j ? i : j;}void menoyy(){ for (int j = 0; j <= W; j++) if (j >= cargo[num].weight) menoy[num][j] = cargo[num].value; else menoy[num][j] = 0; for(int i=num-1;i>=0;i--) for (int j = 0; j <= W; j++) { if (j > cargo[i].weight) menoy[i][j] = max(menoy[i + 1][j], menoy[i + 1][j - cargo[i].weight] + cargo[i].value); else menoy[i][j] = menoy[i + 1][j]; }}void print(){ int w = W; int x[num + 1]; for (int i = 1; i < num; i++) { if (menoy[i][w] == menoy[i + 1][w]) x[i] = 0; else { x[i] = 1; w = w - cargo[i].weight; } } x[num] = menoy[num][W] ? 1 : 0; for (int i = 1; i <= num; i++) cout << i << '\t'; cout << endl; for (int i = 1; i <= num; i++) cout << x[i] << '\t';}int main(){ menoyy(); print(); while (1); return 0;}

  

 

转载于:https://www.cnblogs.com/linear/p/6683294.html

你可能感兴趣的文章
Jvm(16),jvm创建对象---对象在内存中的创建
查看>>
Microsoft SQL Server 2005 Service fails to start
查看>>
【048】HTML 笔记
查看>>
RDA 编译器的搭建
查看>>
sqlserver重命名字段名称
查看>>
学习面试题Day07
查看>>
HttpServletRequest/HttpServletResponse乱码问题解决
查看>>
yum源配置
查看>>
Python操作redis
查看>>
spring+springmvc+mybatis+maven整合
查看>>
(原)ubuntu中安装tensorflow
查看>>
如何设置双网卡路由
查看>>
组策略导入导出secedit
查看>>
Windows Phone 7.5 - Local SQL Database(简介)
查看>>
微软宣布Entity Framework 5的性能有了显著提升
查看>>
SPSS中八类常用非参数检验之二:二项分布(Binomial)检验
查看>>
mysql字段类型范围说明:int、bigint、smallint、tinyint,char、varchar、nvarchar
查看>>
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
查看>>
C# Socket编程(5)使用TCP Socket
查看>>
SQL SERVER IN参数化处理
查看>>