动态规划法-01背包问题

一 几个概念:

最优化问题:有n个输入,它的解由这n个输入的一个子集组成,这个子集必须满足某些事先给定的条件,这些条件称为约束条件,满足约束条件的解称为问题的可行解。满足约束条件的可行解可能不止一个,为了衡量这些可行解的优劣,事先给出一定的标准,这些标准通常以函数的形式给出,这些标准函数称为目标函数,使目标函数取得极值的可行解成为最优解,这类问题称为最优化问题。

二 最优性原理:

对于一个具有n个输入的最优化问题,其求解的过程往往可以划分为若干个阶段,每一个阶段的决策仅依赖前一阶段的状态,由决策所采取的动作使状态发生转移,成为下一个阶段的依据。从而,一个决策序列在不断变化的状态中产生。这个决策序列产生的过程称为多阶段决策过程。

在每一个阶段的决策中有一个赖以决策的策略或目标,这种策略或目标是由问题的性质和特点所确定,通常以函数的形式表示并具有递推关系,称为动态规划函数。

多阶段决策过程满足最优性原理:无论决策过程的初始状态和初始决策是什么,其余决策必须相对于初始决策所产生的当前状态,构成一个最优决策序列。

如果一个问题满足最优性原理通常称此问题具有最优子结构性质。

三 特征

我们知道动态规划是求解全局最优解的有效方法,一般来说能用动态规划算法求解的问题具有以下两个显著特称:

  • 具有最优子结构性质,也就是说可以递归的定义最优解。
  • 能够分解为相互重叠的若干自问题。
  • 最优解中也包含其子问题的最优解。

四 设计方案

动态规划法设计方案

  • 分段:将原问题分解为若干个相互重叠的子问题;
  • 分析:分析问题是否满足最优子结构性质,找出动态规划函数递推式;
  • 求解:利用递推式自底向上计算,实现动态规划过程。

五 01背包问题

0/1背包问题中,物品i或者被放入背包,或者不被放入背包,设Xi表示物品i装入背包的情况,则当Xi=0时,表示物品i没有被装入背包,Xi=1时,表示物品i被装入背包。根据问题的要求,有如下约束条件和目标函数:

图 1 约束条件

图2 目标函数

01背包的状态转换方程f[i,j]=
Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] }

f[i,j]表示在前i件物品中选择若干件放在承重为j的背包中,可以取得的最大价值。

Pi表示第i件物品的价值。

决策:为了背包中物品总价值最大化,第i件物品应该放入背包中吗?

六 动态规划法解决方案

有编号分别为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

表10/1背包问题动态规划法

表1采用自底向上自左向右的方式生成的。

e1表示在背包容量为1的情况下仅仅放入物品e的价值,因容量1<4因此价值为0;依此类推当背包容量为4时,单元格e4的价值为6。容量继续上涨也只能放置e,因此价值持续为6。

d行可参照递推式f[i,j]=
Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }如下描述

  1. i<=5时,d行表格价值与e行相同;
  2. i>=6时,比如第6行,选取Max{f[1,1]+4,f[1,6]}即Max{e1+4,
    e6}=Max{4, 6} = 6;依此类推d9=Max{f[1,4]+4,f[1,59}=10;

依次类推可计算c/b/a的值,然后根据最大价值返算最优路径。

d1表示背包容量为1的情况下放置物品d和e后的价值,因e的重量为4>1,且d的重量为5>1因此价值为0。直至第5列(不包括d5)d行表格的内容与e行相同,

七 程序实现C#

代码段1 测试函数

class MainClass
	{
		public static void Main (string[] args)
		{
            Obj[] objs = new Obj[4];
            objs[0] = new Obj() { Weight = 7, Price = 42 };
            objs[1] = new Obj() { Weight = 3, Price = 12 };
            objs[2] = new Obj() { Weight = 4, Price = 40 };
            objs[3] = new Obj() { Weight = 5, Price = 25 };

            			Console.WriteLine ("Dynamicprogramming Model:");
			dynamicprogramming d = new dynamicprogramming (objs, 10);
			int price = d.Execute ();
			d.Printing (price);
            //Console.Read();
		}
	}

代码段2 实现函数

public class dynamicprogramming
	{
		/// <summary>
		/// 存储动态规划的递推数据
		/// m_V[i][j]表示前i个物品放入容量为j的背包获得的最大价值
		/// 其中第0行作为初始化,表示不放入物品时的价值;
		/// 第0列作为初始化,表示容量为0时能放入物品的价值;
		/// </summary>
		private int[,] m_V;
		/// <summary>
		/// 物品数量
		/// </summary>
		private int m_n;
		/// <summary>
		/// 背包容量
		/// </summary>
		private int m_w;

		public Obj[] objs {
			get;
			set;
		}
		public dynamicprogramming (Obj[] objs, int w)
		{
			if (objs == null) {
				return;
			}

			m_n = objs.Length;
			this.objs = objs;
			m_w = w;
			m_V = new int[m_n + 1, m_w + 1];

			for (int i = 0; i < m_w+1; i++) {
				m_V [0, i] = 0;
			}
			for (int i = 0; i < m_n+1; i++) {
				m_V [i, 0] = 0;
			}
		}

		public int Execute()
		{
			for (int r = 1; r <= m_n; r++) {
				for (int w = 1; w <= m_w; w++) {
					if (w < objs[r - 1].Weight) {
						m_V[r, w] = m_V[r - 1, w];
					} else {
						int tmp = m_V [r - 1, w - objs [r - 1].Weight] + objs [r - 1].Price;
						m_V [r, w] = m_V [r - 1, w] > tmp ? m_V [r - 1, w] : tmp;
					}
				}
			}

			//求装入背包的物品
			int weight = m_w;
			for (int i = m_n; i > 0; i--) {
				if (m_V[i, weight] > m_V[i - 1, weight]) {
					objs [i - 1].Selected = true;

					weight -= objs [i - 1].Weight;
				}
			}

			return m_V[m_n, m_w];
		}

		public void Printing(int price)
		{
			Console.Write("<");
			for (int i = 0; i < objs.Length; i++)
			{
				Console.Write(objs[i].Selected ? "1 " : "0 ");

			}
			Console.WriteLine(">, price: " + price );
		}
	}

输出结果:

注:上述程序使用FreeBSD下Mono开发。

动态规划法-01背包问题

时间: 2024-11-09 01:02:03

动态规划法-01背包问题的相关文章

动态规划法—0-1背包问题(一)

0-1背包问题 问题描述 给定n个物品和一背包.物品i的重量是wi,其价值为vi,背包的容量为W.应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 约束条件 放入背包的物品的重量<=背包容量W 物品只能进入背包或不进入背包,不可拆分,区别于部分背包问题. 求解目标 我们可以这样来刻画问题的解. 假如有n个物品,用Xi表示第i个物品的状态.Xi 的值为0或1.0表示物品未进入背包,1表示物品进入背包. 那么问题的解就是一个集合(X1,X2,X3,-,Xi,-,Xn) . 所以,我们就是要

动态规划法—0-1背包问题(二)

问题的描述 假如我们用C表示最大价值,那么C[n,W]就表示n个物品,在背包容量为W时,背包的最大价值. 在求这个最大价值之前,我们可能会考虑某一子问题的最大价值,用C[i,w]表示,意思是该子问题中,有i个物品,背包的最大容量为w时的最大价值. 三种情况 情况1:假如这个子问题中,i=0或w=0,那么c[i,w]=0. 情况2:假如在该子问题中,在i个物品当中,有的物品根本就装不进背包(该物品的wi>w),那么根本就谈不到它在背包价值大的还是不在背包价值大,所以直接将该子问题转化成c[i-1,

动态规划法——求解0-1背包问题

问题描述 0-1背包问题与背包问题(贪心法--背包问题)最大的不同就是背包问题的子问题彼此之间没有联系,所以只要找出解决方法,然后用贪心算法,取得局部最优解就ok了,但是0-1背包问题更复杂,因为物品不可再分,导致了子问题之间是有联系的. 问题分析 1,刻画背包问题最优解的结构 2,数学描述 伪代码解读 当上段代码运算完成之后,对于C[i,w]的表: 然后根据上面构造的表,求最优解: 小结 动态规划法在判断是否含有第i个物品时,通过判断C[I,w]是否等于C[i-1,w]来得出是否含有第i个物品

0-1背包问题——动态规划法

问题描述:给定n种物品和一背包.物品i的重量是w[i],其价值为v[i],背包的容量为C.问应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 分析:对于一种物品,要么装入背包,要么不装.所以对于一种物品的装入状态可以取0和1.设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-1背包问题. 数据:物品个数n=5,物品重量w[5]={2,2,6,5,4},物品价值v[5]={6,3,5,4,6},总重量c=10.背包的最大容量为10,那么在设置数组m大小时,可以设行列值为5和10

0-1背包问题的动态规划法与回溯法

一.动态规划 状态转移方程: 1 从前往后: 2 if(j>=w[i]) 3 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]); 4 else 5 m[i][j]=m[i-1][j]; 6 7 从后往前: 8 if(j>=w[i]) 9 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]); 10 else 11 m[i][j]=m[i+1][j]; 算法: 1 从前往后: 2 for(int i=1;i<=n;i++)

动态规划算法--01背包问题

基本思想: 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解.动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解.与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解).若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很

动态规划的详细解析(01背包问题)

                                  算法分析之动态规划详解 先举个例子01背包问题具体例子:假设现有容量15kg的背包,另外有4个物品,分别为a1,a2,a3, a4.物品a1重量为3kg,价值为4:物品a2重量为4kg,价值为5:物品a3重量为5kg,价值为6, a4重6千克,价值为7.将哪些物品放入背包可使得背包中的总价值最大? 对于这样的问题,如果如上述所涉及的数据比较少的时候,我们通过列举就能算出来,例如,上边的例子的答案是:将a4和a3与a2放入背包中,

01背包问题回溯法和动态规划

题目要求: 输入背包的容量v和物品的数量n:接下来n 行每行输入两个数字,第一个是物品质量,第二个是物品价值: 输出背包容纳物品的最大价值. 下面直接贴代码: 回溯法 1 #include<iostream>//之前必须知道背包容量和n个物品 2 #include<algorithm> 3 using namespace std; 4 class Property 5 { 6 public: 7 int weight,profit; 8 double average; 9 frie

0-1背包问题——动态规划

1 // 动态规划法解决0-1背包问题 2 //example: 3 //物品种类n=5,背包容量c=10, 4 //物品的重量向量 w={2,2,6,5,4},物品的价值向量 v={6,3,5,4,6} 5 // O(min{n*c,2^n}) 6 #include "stdafx.h" 7 #include <cstdlib> 8 #include <iostream> 9 10 using namespace std; 11 template<cla