0-1背包问题之动态规划法 -
动态规划与回溯法解决0-1背包问题

0-1背包动态规划解决问题一、问题描述:有n个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?二、总体思路:根据动态规划解题步骤(问题抽象化、建立模型、寻找约束条件、判断是否满足最优性原理、找大问题与小问题的递推关系式、填表、寻找解组成)找出01背包问题的最优解以及解组成,然后编写代码实现。
原理:动态规划与分治法类似,都是把大问题拆分成小问题,通过寻找大问题与小问题的递推关系,解决一个个小问题,最终达到解决原问题的效果。
但不同的是,分治法在子问题和子子问题等上被重复计算了很多次,而动态规划则具有记忆性,通过填写表把所有已经解决的子问题答案纪录下来,在新问题里需要用到的子问题可以直接提取,避免了重复计算,从而节约了时间,所以在问题满足最优性原理之后,用动态规划解决问题的核心就在于填表,表填写完毕,最优解也就找到。
过程:a) 把背包问题抽象化(X1,X2,…,Xn,其中 Xi 取0或1,表示第i 个物品选或不选),V i表示第i 个物品的价值,W i表示第i 个物品的体积(重量);b) 建立模型,即求max(V1X1+V2X2+…+VnXn);c) 约束条件,W1X1+W2X2+…+WnXn<capacity;d) 定义V(i,j):当前背包容量j,前i 个物品最佳组合对应的价值;e) 最优性原理是动态规划的基础,最优性原理是指“多阶段决策过程的最优决策序列具有这样的性质:不论初始状态和初始决策如何,对于前面决策所造成的某一状态而言,其后各阶段的决策序列必须构成最优策略”。
判断该问题是否满足最优性原理,采用反证法证明:假设(X1,X2,…,Xn)是01背包问题的最优解,则有(X2,X3,…,Xn)是其子问题的最优解,假设(Y2,Y3,…,Yn)是上述问题的子问题最优解,则理应有(V2Y2+V3Y3+…+V n Yn)+V1X1 > (V2X2+V3X3+…+VnXn)+V1X1;而(V2X2+V3X3+…+VnXn)+V1X1=(V1X1+V2X2+…+VnXn),则有(V2Y2+V3Y3+…+VnYn)+V1X1 > (V1X1+V2X2+…+VnXn);该式子说明(X1,Y2,Y3,…,Yn)才是该01背包问题的最优解,这与最开始的假设(X1,X2,…,Xn)是01背包问题的最优解相矛盾,故01背包问题满足最优性原理;f) 寻找递推关系式,面对当前商品有两种可能性:第一,包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);第二,还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i) }其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i)但价值增加了v(i);由此可以得出递推关系式:1) j<w(i) V(i,j)=V(i-1,j)2) j>=w(i) V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }number=4,capacity=7四、构造最优解:最优解的构造可根据C列的数据来构造最优解,构造时从第一个物品开始。
动态规划——01背包问题

动态规划——01背包问题⼀、最基础的动态规划之⼀01背包问题是动态规划中最基础的问题之⼀,它的解法完美地体现了动态规划的思想和性质。
01背包问题最常见的问题形式是:给定n件物品的体积和价值,将他们尽可能地放⼊⼀个体积固定的背包,最⼤的价值可以是多少。
我们可以⽤费⽤c和价值v来描述⼀件物品,再设允许的最⼤花费为w。
只要n稍⼤,我们就不可能通过搜索来遍查所有组合的可能。
运⽤动态规划的思想,我们把原来的问题拆分为⼦问题,⼦问题再进⼀步拆分直⾄不可再分(初始值),随后从初始值开始,尽可能地求取每⼀个⼦问题的最优解,最终就能求得原问题的解。
由于不同的问题可能有相同的⼦问题,⼦问题存在⼤量重叠,我们需要额外的空间来存储已经求得的⼦问题的最优解。
这样,可以⼤幅度地降低时间复杂度。
有了这样的思想,我们来看01背包问题可以怎样拆分成⼦问题:要求解的问题是:在n件物品中最⼤花费为w能得到的最⼤价值。
显然,对于0 <= i <= n,0 <= j <= w,在前i件物品中最⼤花费为j能得到的最⼤价值。
可以使⽤数组dp[n + 1][w + 1]来存储所有的⼦问题,dp[i][j]就代表从前i件物品中选出总花费不超过j时的最⼤价值。
可知dp[0][j]值⼀定为零。
那么,该怎么递推求取所有⼦问题的解呢。
显⽽易见,要考虑在前i件物品中拿取,⾸先要考虑前i - 1件物品中拿取的最优情况。
当我们从第i - 1件物品递推到第i件时,我们就要考虑这件物品是拿,还是不拿,怎样收益最⼤。
①:⾸先,如果j < c[i],那第i件物品是⽆论如何拿不了的,dp[i][j] = dp[i - 1][j];②:如果可以拿,那就要考虑拿了之后收益是否更⼤。
拿这件物品需要花费c[i],除去这c[i]的⼦问题应该是dp[i - 1][j - c[i]],这时,就要⽐较dp[i - 1][j]和dp[i - 1][j - c[i]] + v[i],得出最优⽅案。
数据结构 背包问题

数据结构背包问题背包问题是计算机科学中一个经典的优化问题,它涉及到在给定的一组物品中选择一些物品放入背包中,以使得背包的总分量不超过背包的容量,并且所选择的物品的总价值最大化。
在解决背包问题时,往往使用数据结构来存储和操作物品的信息,以便高效地求解最优解。
一种常见的背包问题是0/1背包问题,即每一个物品要末选择放入背包中,要末选择不放入背包中。
假设有n个物品,每一个物品有一个分量w和一个价值v,背包的容量为C。
要求选择哪些物品放入背包中,以使得背包的总分量不超过C,并且所选择的物品的总价值最大化。
为了解决0/1背包问题,可以使用动态规划的方法。
首先,定义一个二维数组dp,其中dp[i][j]表示在前i个物品中,背包容量为j时,所选择的物品的总价值的最大值。
然后,根据动态规划的思想,可以得到如下的状态转移方程:当i=0或者j=0时,dp[i][j]的值为0,表示没有物品可选或者背包容量为0时,所选择的物品的总价值为0;当j<w[i]时,dp[i][j]的值等于dp[i-1][j],表示当前物品的分量大于背包的容量,无法放入背包中,所以选择不放入;当j>=w[i]时,dp[i][j]的值等于max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),表示当前物品的分量小于等于背包的容量,可以选择放入或者不放入背包中,选择其中总价值较大的方案。
通过填充dp数组,最终dp[n][C]即为所需的最优解,表示在前n个物品中,背包容量为C时,所选择的物品的总价值的最大值。
举个例子来说明背包问题的求解过程。
假设有如下的物品和背包容量:物品1:分量2,价值6物品2:分量2,价值10物品3:分量3,价值12物品4:分量4,价值14背包容量为7。
首先,创建一个4行8列的二维数组dp,初始化dp[0][j]和dp[i][0]的值为0。
填充dp数组的过程如下:对于dp[1][j],当j=0~7时,由于物品1的分量为2,所以当j<2时,dp[1][j]的值为0;当j>=2时,dp[1][j]的值为6,表示选择物品1放入背包中。
分支界限方法01背包问题解题步骤

分支界限方法是一种用于解决优化问题的算法。
在动态规划算法中,分支界限方法被广泛应用于解决01背包问题。
01背包问题是一个经典的动态规划问题,其解题步骤如下:1. 确定问题:首先需要明确01背包问题的具体描述,即给定一组物品和一个背包,每个物品有自己的价值和重量,要求在不超过背包容量的情况下,选取尽可能多的物品放入背包,使得背包中物品的总价值最大。
2. 列出状态转移方程:对于01背包问题,可以通过列出状态转移方程来描述问题的求解过程。
假设dp[i][j]表示在前i个物品中,背包容量为j时能够获得的最大价值,则状态转移方程可以表示为:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])3. 初始化边界条件:在动态规划中,需要对状态转移方程进行初始化,一般情况下,dp数组的第一行和第一列需要单独处理。
对于01背包问题,可以初始化dp数组的第一行和第一列为0。
4. 利用分支界限方法优化:针对01背包问题,可以使用分支界限方法来优化动态规划算法的效率。
分支界限方法采用广度优先搜索的思想,在每一步选择最有希望的分支,从而减少搜索空间,提高算法的效率。
5. 实际解题步骤:根据上述步骤,实际解决01背包问题的步骤可以概括为:确定问题,列出状态转移方程,初始化边界条件,利用分支界限方法优化,最终得到问题的最优解。
分支界限方法在解决01背包问题时起到了重要的作用,通过合理的剪枝策略,可以有效地减少动态规划算法的时间复杂度,提高问题的求解效率。
分支界限方法也可以应用于其他优化问题的求解过程中,在算法设计和实现中具有重要的理论和实际意义。
在实际应用中,分支界限方法需要根据具体问题进行灵活选择和调整,结合动态规划和剪枝策略,以便更好地解决各类优化问题。
掌握分支界限方法对于解决复杂问题具有重要的意义,也是算法设计和优化的关键技术之一。
分支界限方法在解决01背包问题的过程中,具有重要的作用。
蛮力法、动态规划法、回溯法和分支限界法求解01背包问题【精选】

一、实验内容:分别用蛮力法、动态规划法、回溯法和分支限界法求解0/1背包问题。
注:0/1背包问题:给定种物品和一个容量为的背包,物品的重n C i 量是,其价值为,背包问题是如何使选择装入背包内的物品,使得装i w i v 入背包中的物品的总价值最大。
其中,每种物品只有全部装入背包或不装入背包两种选择。
二、所用算法的基本思想及复杂度分析:1.蛮力法求解0/1背包问题:1)基本思想:对于有n 种可选物品的0/1背包问题,其解空间由长度为n 的0-1向量组成,可用子集数表示。
在搜索解空间树时,深度优先遍历,搜索每一个结点,无论是否可能产生最优解,都遍历至叶子结点,记录每次得到的装入总价值,然后记录遍历过的最大价值。
2)代码:#include<iostream>#include<algorithm>using namespace std;#define N 100//最多可能物体数struct goods //物品结构体{int sign;//物品序号int w;//物品重量int p;//物品价值}a[N];bool m(goods a,goods b){return (a.p/a.w)>(b.p/b.w);}int max(int a,int b){return a<b?b:a;}int n,C,bestP=0,cp=0,cw=0;int X[N],cx[N];/*蛮力法求解0/1背包问题*/int Force(int i){if(i>n-1){if(bestP<cp&&cw+a[i].w<=C){for (int k=0;k<n;k++)X[k]=cx[k];//存储最优路径bestP=cp;}return bestP;}cw=cw+a[i].w;cp=cp+a[i].p;cx[i]=1;//装入背包Force(i+1);cw=cw-a[i].w;cp=cp-a[i].p;cx[i]=0;//不装入背包Force(i+1);return bestP;}int KnapSack1(int n,goods a[],int C,int x[]){Force(0);return bestP;}int main(){goods b[N];printf("物品种数n: ");scanf("%d",&n);//输入物品种数printf("背包容量C: ");scanf("%d",&C);//输入背包容量for (int i=0;i<n;i++)//输入物品i 的重量w 及其价值v {printf("物品%d 的重量w[%d]及其价值v[%d]:",i+1,i+1,i+1);scanf("%d%d",&a[i].w,&a[i].p);b[i]=a[i];}int sum1=KnapSack1(n,a,C,X);//调用蛮力法求0/1背包问题printf("蛮力法求解0/1背包问题:\nX=[ ");for(i=0;i<n;i++)cout<<X[i]<<" ";//输出所求X[n]矩阵printf("]装入总价值%d\n",sum1);bestP=0,cp=0,cw=0;//恢复初始化}3)复杂度分析:蛮力法求解0/1背包问题的时间复杂度为:。
蛮力法、动态规划法 求解01背包问题

else
v[i][j]=v[i-1][j];
}
else v[i][j]=v[i-1][j];
}
return v[n][m];
}
int main()
{
int m,n;int i,j;
cout<<"请输入背包的承重量:"<<endl;
2)复杂度分析:2n
2、动态规划法
1)基本思想:Dynamic programming is a technique for solving problems with overlapping subproblems.The function:
V(i,0)=V(0,j)=0;(1)
V(i-1,j)j<w
if (cur_weight <= capacity && cur_value > max_value) {
max_value = cur_value;
}
return;
}
c[d] = 0;
MFKnapsack(capacity, values, weights, c,
d + 1, max_value);
cout << MFKnapsack(capacity, values, weights, n) << endl;
return 0;
}
(2)Dynamic Programming
#include<iostream.h>
#include<string.h>
int v[10][100];//对应每种情况的最大价值
用蛮力法、动态规划法和贪心法求解0 1背包问题

printf("\n");
}
}
以下要依次判断每个子集的可行性,找出可行解:
voidpanduan(inta[][4],intcw[])////判断每个子集的可行性,如果可行则计算其价值存入数组cw,不可行则存入0
{
int i,j;
int n=16;
int sw,sv;
for(i=0;i<16;i++)
用蛮力法解决0/1背包问题,需要考虑给定n个物品集合的所有子集,找出所有可能的子集(总重量不超过背包容量的子集),计算每个子集的总价值,然后在他们中找到价值最大的子集。
所以蛮力法解0/1背包问题的关键是如何求n个物品集合的所有子集,n个物品的子集有2的n次方个,用一个2的n次方行n列的数组保存生成的子集,以下是生成子集的算法:void force(int a[][4])//蛮力法产生4个物品的子集
{
int i,j;
int n=16;
int m,t;
for(i=0;i<16;i++)
{t=i;
for(j=3;j>=0;j--)
{
m=t%2;
a[i][j]=m;
t=t/2;
}
}
for(i=0;i<16;i++)//输出保存子集的二维数组
{
for(j=0;j<4;j++)
{
printf("%d",a[i][j]);
i++;
}
return maxprice;
}
#include<stdio.h>
#include<stdlib.h>
0-1背包问题的动态规划法与回溯法

0-1背包问题的动态规划法与回溯法⼀、动态规划状态转移⽅程:1从前往后:2if(j>=w[i])3 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);4else5 m[i][j]=m[i-1][j];67从后往前:8if(j>=w[i])9 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);10else11 m[i][j]=m[i+1][j];算法:1从前往后:2for(int i=1;i<=n;i++)3for(int j=1;j<=c;j++)4 {5if(j>=w[i])6 {7 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);8 }9else//这⾥没有考虑j<0的情况,因为算法中j取不到10 {11 m[i][j]=m[i-1][j];12 }13 }1415从后往前:16for(int i=n;i>=1;i--)17for(int j=1;j<=c;j++)18 {19if(j>=w[i])20 {21 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);22 }23else24 {25 m[i][j]=m[i+1][j];26 }27 }例⼦:例:0-1背包问题。
在使⽤动态规划算法求解0-1背包问题时,使⽤⼆维数组m[i][j]存储背包剩余容量为j,可选物品为i、i+1、……、n时0-1背包问题的最优值。
绘制重量数组w = {4, 6, 2, 2, 5, 1},价值数组v = {8, 10, 6, 3, 7, 2},背包容量C = 12时对应的m[i][j]数组。
(从前往后)例题代码 :1 #include<iostream>2 #include<cmath>3 #include<cstring>4#define N 205using namespace std;6int main()7 {8int w[N]={0,4,6,2,2,5,1},v[N]={0,8,10,6,3,7,2};9int m[N][N];10 memset(m,0,sizeof(m));11int n=6,c=12; //n,c均要⼩于N12for(int i=1;i<=n;i++)13for(int j=1;j<=c;j++)14 {15if(j>=w[i])16 {17 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);18 }19else20 {21 m[i][j]=m[i-1][j];22 }23 }24 cout<<m[n][c]<<endl; //从前往后2526/*27 for(int i=n;i>=1;i--)28 for(int j=1;j<=c;j++)29 {30 if(j>=w[i])31 {32 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);33 }34 else35 {36 m[i][j]=m[i+1][j];37 }38 }39 cout<<m[1][c]<<endl;//从后往前40*/41return0;42 }⼆、回溯法1进⼊左⼦树条件:cw+w[i]<=c //cw为当前重量2进⼊右⼦树条件(减枝函数):cp+r>bestp //cp为当前价值,bestp为当前最优价值,r为当前剩余物品价值总和。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
d(4, 9)=min{c47+d(7, 9), c48+d(8, 9)} d(5, 9)=min{c57+d(7, 9), c58+d(8, 9)} d(6, 9)=min{c67+d(7, 9), c68+d(8, 9)} 这一阶段的决策依赖于d(7, 9)和d(8, 9)的计算,而d(7, 9)和 d(8, 9)可以直接获得(括号中给出了决策产生的状态转移):
d(1, 9)=min{c14+d(4, 9), c15+d(5, 9)}
d(2, 9)=min{c24+d(4, 9), c25+d(5, 9), c26+d(6, 9)} d(3, 9)=min{c35+d(5, 9), c36+d(6, 9)} 这一阶段的决策又依赖于d(4, 9)、d(5, 9)和d(6, 9) 的计算结果:
得到最短路径为0→3→5→8→9,长度为16。
1.2 什么是动态规划
在上例的多阶段决策问题中,各个阶段采取的 决策,一般来说是与时间有关的,决策依赖于当前状 态,又随即引起状态的转移,一个决策序列就是在变 化的状态中产生出来的,故有“动态”的含义,称这 种解决多阶段决策最优化问题的方法为动态规划方法。
1
4
9
8 6
7 8 4 7
4
6
5
0
2 3
2 3
5 6
8
7
6
7
9 8
5
6
3
图1 一个多段图
设G是一个有向加权图,则G从顶点i到顶点j之间的 最短路径问题满足最优性原理。 证明:设i~ip~iq~j是一条最短路径,但其中子路径 ip~iq~j不是最优的, 假设最优的路径为ip~iq’~j, 则我们重新构造一条路径:i~ip~iq’~j 显然该路径长度小于i~ip~iq~j,与i~ip~iq~j 是顶 点i到顶点j的最短路径相矛盾. 所以,原问题满足最优性原理。
d(7, 9)=c79=7(7→9)
d(8, 9)=c89=3(8→9) 再向前推导,有: d(6, 9)=min{c67+d(7, 9), c68+d(8, 9)}=min{6+7, 5+3}=8(6→8) d(5, 9)=min{c57+d(7, 9), c58+d(8, 9)}=min{8+7, 6+3}=9(5→8)
动态规划是运筹学的一个分支。与其说动态规 划是一种算法,不如说是一种思维方法来得更贴切。 因为动态规划没有固定的框架,即便是应用到同一道 题上,也可以建立多种形式的求解算法。许多隐式图 上的算法,例如求单源最短路径的Dijkstra算法、广 度优先搜索算法,都渗透着动态规划的思想。 因此,动态规划不像深度或广度优先那样可以 提供一套模式,需要的时候,取来就可以使用;它必 须对具体问题进行具体分析处理,需要丰富的想象力 去建立模型,需要创造性的思想去求解。
在0/1背包问题中,物品i或者被装入背包,或者不被 装入背包,设xi表示物品i装入背包的情况,则当xi=0 时,表示物品i没有被装入背包,xi=1时,表示物品i 被装入背包。根据问题的要求,有如下约束条件和 目标函数:
n wi xi C i 1 xi {0,1} (1 i n)
d(4, 9)=min{c47+d(7, 9), c48+d(8, 9)}=min{5+7, 6+3}=9(4→8)
d(3, 9)=min{c 3 5 +d(5, 9), c 3 6 +d(6, 9)}=min{4+9, 7+8}=13(3→5)
d(2, 9)=min{c24+d(4, 9), c25+d(5, 9), c26+d(6, 9)}=min{6+9, 7+9, 8+8}=15(2→4) d(1, 9)=min{c 1 4 +d(4, 9), c 1 5 +d(5, 9)}=min{9+9, 8+9}=17(1→5) d ( 0 , 9 ) = min{ c 0 1 +d ( 1 , 9 ) , c 0 2 +d ( 2 , 9 ) , c 0 3 +d ( 3 , 9)}=min{4+17, 2+15, 3+13}=16(0→3)
对多段图的边(u, v),用cuv表示边上的权值,将从源点s 到终点t的最短路径记为d(s, t),则从源点0到终点9的最 短路径d(0, 9)由下式确定:
d(0, 9)=min{c01+d(1, 9), c02+d(2, 9), c03+d(3, 9)}
这是最后一个阶段的决策,它依赖于 d (1, 9)、 d(2, 9)和d(3, 9)的计算结果,而
由于多段图将顶点划分为k个互不相交的子集,所以,多段 图划分为k段,每一段包含顶点的一个子集。根据多段图的定义, 每个子集中的顶点互不邻接。不失一般性,将多段图的顶点按 照段的顺序进行编号,同一段内顶点的相互顺序无关紧要。假 设图中的顶点个数为n,则源点s的编号为0,终点t的编号为n-1, 并且,对图中的任何一条边(u, v),顶点u的编号小于顶点v的编 号。
i 2
i i
i 2
v1x1 vi yi v1x1 vi xi vi xi
i 2 i 1
n
n
,这说明(x1, y2, …, yn)是所给0/1 背包问题比(x1, x2, …, xn)更优的解,从而导致矛盾。
0/1背包问题可以看作是决策一个序列(x1, x2, …, xn),对 任一变量xi的决策是决定xi=1还是xi=0。在对xi-1决策后, 已确定了(x1, …, xi-1),在决策xi时,问题处于下列两种状 态之一:
动态规划
1. 概述
2. 组合问题中的动态规划法
3. 图问题中的动态规划法 4. 查找问题中的动态规划法
1. 概 述
1.1 例题(多段图) 1.2 什么是动态规划 1.3 动态规划适于解决什么样的问题 1.4 最优性原理 1.5 无后效性原则 1.6 动态规划法的设计思想
1.1 多段图的最短路径问题
设图G=(V, E)是一个带权有向连通图,如果把顶点集合V划分成 k个互不相交的子集Vi(2≤k≤n, 1≤i≤k),使得E中的任何一 条边(u, v),必有u∈Vi,v∈Vi+m(1≤i<k, 1<i+m≤k),则称 图G为多段图,称s∈V1为源点,t∈Vk为终点。多段图的最短路 径问题是求从源点到终点的最小代价路径。
例题 余数最少的路径
如图所示,有4个点,分 别是A、B、C、D,相邻两 点用两条连线 C2k,C2k-1(1≤k≤3) 表示两条通行的道路。连线 上的数字表示道路的长度。 定义从A到D的所有路径中, 长度除以4所得余数最小的 路径为最优路径。 求一条最优路径。
【分析】在这个问题中,如果还按照例题1中的方法 去求解就会发生错误。按照例题1的思想,A的最优取值 可以由B的最优取值来确定,而B的最优取值为(1+3) mod 4 = 0,所以A的最优值应为2,而实际上,路径C1 -C3-C5可得最优值为(2+1+1) mod 4 = 0,所以,B 的最优路径并不是A的最优路径的子路径,也就是说, A的最优取值不是由B的最优取值决定的,即其不满足 最优化原理,问题不具有最优子结构的性质。 由此可见,并不是所有的“决策问题”都可以用 “动态规划”来解决,运用“动态规划”来处理问题必 须满足最优化原理。
1.4 最优性原理
作为整个过程的最优策略具有如下性质:无论过去的 状态和决策如何,对前面的决策所形成的当前状态而 言,余下的诸决策必须构成最优策略。 可以通俗地理解为子问题的局部最优将导致整个问题 的全局最优,即问题具有最优子结构的性质,也就是 说一个问题的最优解只取决于其子问题的最优解,非 最优解对问题的求解没有影响。在 例题1 最短路径 问题中,A到E的最优路径上的任一点到终点E的路径 也必然是该点到终点E的一条最优路径,满足最优化 原理。下面来讨论另外一个问题。
n wi xi C w1 x1 i 2 xi {0,1} (2 i n)
如若不然,设(y2, …, yn)是上述子问题的一个最优解, n n n 则 ,且 w1 x1 wi yi 。因此, C
v y v x
i 2 i i i 2 n
可以用动态规划法求解的问题除了能够分解为相互重叠的 若干子问题外,还要满足最优性原理(也称最优子结构性 质),这类问题具有如下特征:该问题的最优解中也包含 着其子问题的最优解。在分析问题是否满足最优性原理时, 通常先假设由问题的最优解导出的子问题的解不是最优的, 然后再设法说明在这个假设下可构造出比原问题最优解更 好的解,从而导致矛盾。 动态规划法利用问题的最优性原理,以自底向上的方 式从子问题的最优解逐步构造出整个问题的最优解。应用 动态规划法设计算法一般分成三个阶段: (1)分段:将原问题分解为若干个相互重叠的子问题; (2)分析:分析问题是否满足最优性原理,找出动态规划 函数的递推式; (3)求解:利用递推式自底向上计算,实现动态规划过程。
1.5 无后效性原则
所谓无后效性原则,指的是这样一种性质:
某阶段的状态一旦确定,则此后过程的演变不 再受此前各状态及决策的影响。也就是说,“未来与 过去无关”,当前的状态是此前历史的一个完整总结, 此前的历史只能通过当前的状态去影响过程未来的演 变。具体地说,如果一个问题被划分各个阶段之后, 阶段 I 中的状态只能由阶段 I+1 中的状态通过状态 转移方程得来,与其他状态没有关系,特别是与未发 生的状态没有关系,这就是无后效性。
(式1) (式2)
max vi xi
i 1