动态规划 例题众多 详细讲解
- 格式:ppt
- 大小:652.50 KB
- 文档页数:59
动态规划运筹学例题动态规划是运筹学中常用的一种优化技术,它利用规划、三角函数和其他数学技术来解决日常生活中的各种问题,比如最优路线问题、最优资源分配问题、最优出行路线问题等。
本文将通过一个例题,来介绍动态规划的基本思想,以及如何利用动态规划来解决问题。
例题一:已知一条路线,由A点到B点,有N个途经的节点,每个节点之间的距离已知。
求从A到B的最短路线。
按照动态规划的思想,首先将该问题分解为若干个子问题,并根据子问题的解来解决原问题,这种分解和解决问题的方式称为动态规划。
对于上面的问题,可以将其分解为N个子问题,分别是从A到第1个节点、从第1个节点到第2个节点、从第2个节点到第3个节点,以此类推,最后一个子问题是从第N-1个节点到B点的最短路程。
将上面的N个子问题中,从第i个节点到B点的最短路程记为d[i],由于从第i个节点到B点可能经过i+1、i+2、……、N-1节点,因此要找到d[i],只需要找到经过i+1、i+2、……、N-1节点的最短路程即可,即求d[i]=Min{d[i+1]+length[i][i+1],d[i+2]+length[i][i+2],…,d[N-1]+length[i][N-1]},其中length[i][j]是第i个节点到第j个节点的距离。
以上就是动态规划的解题步骤,它能将原问题分解成若干个子问题,并找到最优解。
对于本例来说,通过上述步骤,就可以得到从A 到B的最短路程。
这种分解和求解问题的方法是动态规划,可以用来解决许多类似的问题,如:1)最优路线问题;2)旅行推销员问题;3)硬币找零问题。
动态规划的一大特点是,他能很好地将问题分解为多个子问题,并能从子问题的解中求解出最优解。
总之,动态规划是一种很有用的优化技术,它可以有效解决各种运筹学问题。
它不仅可以帮助我们解决许多具体问题,而且还能使我们更好地理解问题及其解法。
例1:机器负荷分配问题某公司新购进1000台机床,每台机床都可在高、低两种不同的负荷下进行生产,设在高负荷下生产的产量函数为g(x )=10x (单位:百件),其中x 为投入生产的机床数量,年完好率为a =0.7;在低负荷下生产的产量函数为h(y)=6y (单位:百件),其中y 为投人生产的机床数量,年完好率为b=0.9。
计划连续使用5年,试问每年如何安排机床在高、低负荷下的生产计划,使在五年内生产的产品总产量达到最高。
例2:某企业通过市场调查,估计今后四个时期市场对某种产品的需要量如下表:时期(k) 12 3 4 需要量(d k )2(单位)324假定不论在任何时期,生产每批产品的固定成本费为3(千元),若不生产,则为零;生产单位产品成本费为1(千元);每个时期生产能力所允许的最大生产批量为不超过6个单位,则任何时期生产x 个单位产品的成本费用为:若 0<x ≤6 , 则生产总成本=3十1·x 若 x =0 , 则生产总成本=0又设每个时期末未销售出去的产品,在一个时期内单位产品的库存费用为0.5(千元),同时还假定第1时期开始之初和在第4个时期之末,均无产品库存。
现在我们的问题是;在满足上述给定的条件下,该厂如何安排各个时期的生产与库存,使所花的总成本费用最低?例3:设某企业在第一年初购买一台新设备,该设备在五年内的年运行收益、年运行费用及更换新设备的净费用如下表:(单位:万元)年份(k) 役龄(t) 运行收益()k g t 运行费用()k r t 更新费用()k c t 第一年 0 22 6 18 第二年0 123 216 819 22第三年0122321185710192328第四年01232422191657101520243038第五年01234252320171446914202024303848试为该企业制定一个五年中的设备更新策略,使得企业在五年内总收益达到最大?例4:设有一辆栽重为10吨的卡车,用以装载三种货物,每种货物的单位重量及单件价值如表所示,问各种货物应装多少件,才能既不超过总重量又使总价值最大?货物 1 2 3单位重量 3 4 5单件价值 4 5 6。
动态规划典型案例解析及计算过程梳理动态规划(Dynamic Programming)是一种通过将问题分解为子问题来解决复杂问题的算法策略。
它通常用于优化问题,通过将问题的解决方案划分为相互重叠的子问题来降低计算复杂度。
下面将通过几个典型案例,详细解析动态规划的应用及其计算过程。
1. 斐波那契数列斐波那契数列是一种经典的动态规划问题。
它的定义是:F(n) =F(n-1) + F(n-2),其中F(0) = 0,F(1) = 1。
我们需要计算第n个斐波那契数。
通过动态规划的思想,可以将该问题划分为子问题,即计算第n-1和第n-2个斐波那契数。
可以使用一个数组来保存已经计算过的斐波那契数,避免重复计算。
具体的计算过程如下:1. 初始化一个长度为n+1的数组fib,将fib[0]设置为0,fib[1]设置为1。
2. 从i=2开始遍历到n,对于每个i,计算fib[i] = fib[i-1] + fib[i-2]。
3. 返回fib[n]作为结果。
通过上述过程,我们可以快速地得到第n个斐波那契数。
这个案例展示了动态规划的重要特性,即将问题分解为子问题进行求解,并利用已经计算过的结果来避免重复计算。
2. 背包问题背包问题是另一个常见的动态规划问题。
问题的定义是:有一组物品,每个物品有自己的重量和价值,在限定的背包容量下,如何选择物品使得背包中的总价值最大化。
通过动态规划的思想,背包问题可以被划分为子问题。
我们可以定义一个二维数组dp,其中dp[i][j]表示在前i个物品中,背包容量为j时的最大价值。
具体的计算过程如下:1. 初始化一个大小为n+1行,m+1列的二维数组dp,其中n为物品数量,m为背包容量。
将所有元素初始化为0。
2. 从i=1开始遍历到n,对于每个i,从j=1开始遍历到m,对于每个j,进行如下判断:- 若当前物品的重量大于背包容量j,则dp[i][j] = dp[i-1][j],即不选择当前物品;- 若当前物品的重量小于等于背包容量j,则dp[i][j] = max(dp[i-1][j], dp[i-1][j-wi] + vi),即选择当前物品或不选择当前物品所能获得的最大价值。
动态规划算法的常见实例动态规划算法是一种将复杂问题分解为简单子问题来解决的算法,它可被应用于多个领域中,如经济学、生物学、计算机科学等。
在本文中,我们将详细讨论动态规划算法的常见实例。
一、最长公共子序列问题最长公共子序列(LCS)问题是一个经典的计算机科学问题,它要求在两个字符串中找到最长的相同连续子序列。
例如,对于字符串“ABCD”和“ACDF”,最长公共子序列为“ACD”。
使用动态规划方法来解决LCS问题。
首先定义一个m行n列的二维矩阵,其中m和n分别表示两个字符串的长度。
然后,使用以下递推关系:1. 如果一个字符串的长度为0,LCS为0。
2. 如果两个字符不相同,则LCS为它们的前一个字符集合和它们的后一个字符集合的最大值。
3. 如果两个字符相同,则LCS为它们的前一个字符集合和它们的后一个字符集合所组成的子序列中的最大值加1。
最后,矩阵右下角的值就是LCS的长度。
二、背包问题背包问题(Knapsack problem)是一个经典的组合优化问题,被广泛应用于计算机科学和其他领域。
在一个决策者必须决定是否将某些物品放入背包中的场景中,背包问题就发挥了作用。
具体来说,我们要解决的问题是:对于一个固定容量的背包,有一些物品,它们的重量和价值都不同,如何在不超过背包容量的前提下,使所装载物品的总价值最大化。
一种解决方案是使用动态规划方法。
定义一个二维数组,其行表示物品,列表示背包大小。
然后,使用以下递推关系:1. 如果所考虑的物品重量大于背包容量,则不选此物品。
2. 否则,在选取该物品和不选该物品两种情况中选择最优解作为最终结果。
最后,矩阵中右下角的值就是最大的总价值。
三、矩阵链乘法矩阵链乘法是一种计算矩阵乘积的优化算法。
它使用动态规划算法来确定矩阵乘积的最小值。
对于一个长度为n的矩阵链,我们可以定义一个n×n 的矩阵M,其中第i行第j列的元素Mi,j表示第i个矩阵与第j个矩阵相乘的最小次数。
第9章动态规划应用举例习题详解(习题)9. 1有一部货车每天沿着公路给四个零售店卸下6箱货物,如果各零售店出售该货物所得利润如表9-1所示,试求在各零售店卸下几箱货物,能使获得总利润最大?其值是多少?9.2设有某种肥料共6个单位重量,准备供给四块粮田用。
其每块田施肥数量与增产粮食数字关系如表9-2所示。
试求对每块田施多少单位重量的肥料,才使总的增产粮食最多。
粮田增肥1234000001202518282424539473605761654756578745857090806907395859.3某公司打算向它的三个营业区增设六个销售店,每个营业区至少增设一个。
从各区赚取的利润(单位为万元)与增设的销售店个数有关,其数据如表9-3所示。
销售店增加数A区利润B区利润C区利润9.4某工厂有100台机器,拟分四个周期使用,在每一周期有两种生产任务。
据经验,把机器q 台投入第一种生产任务,则在一个生产周期中将有;n/3台机器作废;余下的机器全部投入第二种生产任务,则有1/10台机器作废。
如果干第一种生产任务每台机器可收益10, 干第二种生产任务每台机器可收益7。
问怎样分配机器,使总收益最大?9. 5设有三种资源,每单位的成本分别为a、b. co给定的利润函数为n(xi, yi,z),(/ = 1,2,•••,«)现有资金为W,应购买各种资源多少单位分配给"个行业,才能使总利润最大。
试给出动态规划的公式,并写出它的一维递推关系式。
9. 6某厂生产一种产品,估计该产品在未来4个月的销售量分别为400、500、300、200件。
该项产品的生产准备费用每批为500元,每件的生产费用为1元,存储费用每件每月为1 元。
假定1月初的存货为100件,4月底的存货为零。
试求该厂在这4个月内的最优生产计划。
9.7某电视机厂为生产电视机而需生产喇叭,生产以万只为单位。
根据以往记录,一年的四个季度需要喇叭分别是3万、2万、3万、2万只。
第一题导弹拦截本题第一问实际上是给出数列a1..a n,求最长非递增序列的长度,{容易想到以n来划分子问题,即分别求a1..a n-1, a1..a n-2, …, a1,中最长非递增序列长度,但各级子问题之间不易建立转化关系}将子问题具体一些,我们可以用f[k]表示数列a1..a k中以a k结尾的最长非递增序列的长度,题目所求即为max{f[1..n]}。
转移方程为f[n]=max{f[k]}+1;(0<=k<n,a[n]<=a[k] )设a[0]= -maxint,f[0]=0;第二问可以用贪心做,设拦截前k个导弹用o2个系统,其最后拦截的高度分别为l[1]..l[o2],则拦截第k+1个导弹时,找能够拦截这枚导弹的系统中最后拦截高度最小的,若没有这样的系统则新增一个系统。
附源程序:const max = 10000;type arr = array[0..max]of integer;var d,l : arr;i,j,k,m,n,o1,o2,t : longint;procedure input;beginfillchar(d,sizeof(d),0);fillchar(l,sizeof(l),0);writeln('input:');i:=0;repeati:=i+1;read(d[i]);until eoln;t:=i;o1:=0; o2:=0;end;procedure output;beginwriteln('Output:');writeln(o1);writeln(o2);end;procedure main1;beginl[t]:=1;for i:=t-1 downto 1 do begink:=0;for j:=i+1 to t doif (l[j]>k)and(d[i]>=d[j]) then k:=l[j];l[i]:=k+1;end;for i:=1 to t doif l[i]>o1 then o1:=l[i];end;procedure main2;beginfor i:=0 to t do l[i]:=maxint;o2:=1;for i:=1 to t do begink:=0;for j:=1 to o2 doif (l[j]>=d[i])and(l[j]<=l[k]) then k:=j;if k=0 then begino2:=o2+1;k:=o2;end;l[k]:=d[i];end;end;begininput;main1;main2;output;end.第二题 石子合并设f[i,j](i<=j)表示将第i 堆到第j 堆石子合并为一堆所得的最大分数(最小时类似)。
常见动态规划题⽬详解1.爬楼梯题⽬描述:假设你正在爬楼梯。
需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。
你有多少种不同的⽅法可以爬到楼顶呢?注意:给定 n 是⼀个正整数。
⽰例 1:输⼊: 2输出: 2解释:有两种⽅法可以爬到楼顶。
1. 1 阶 + 1 阶2. 2 阶⽰例 2:输⼊: 3输出: 3解释:有三种⽅法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶2. 1 阶 + 2 阶3. 2 阶 + 1 阶实现代码:class Solution {public:int climbStairs(int n) {vector<int> a(n);a[0] = 1;a[1] = 2;if(n == 1){return 1;}if(n == 2){return 2;}for(int i = 2; i < n;i++){a[i] = a[i - 1] + a[i - 2];}return a[n - 1];}};2.变态跳台阶题⽬描述:⼀只青蛙⼀次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。
求该青蛙跳上⼀个n级的台阶总共有多少种跳法。
实现代码:class Solution {public:int jumpFloorII(int number) {if(number == 0){return 0;}int total = 1;for(int i = 1; i < number; i++){total *= 2;}return total;}};3.n年后⽜的数量题⽬描述:假设农场中的母⽜每年会产⽣⼀头⼩母⽜,并且永远不会死。
第⼀年农场中只有⼀头成熟的母⽜,第⼆年开始,母⽜开始⽣⼩母⽜,每只⼩母⽜三年之后成熟⼜可以⽣⼩母⽜,给定整数N,求N年后母⽜的数量。
实现代码:class solution{ public: int f(int n){ if(n < 1){ return 0; } if(n == 1|| n== 2||n == 3){ return n; } int res = 3; int pre = 2; int prepre = 1; int tmp1=0; int tmp2 = 0; for(int i = 4;i < n;i++){ tmp1 = res; tmp2 = pre; res = pre + prepre; pre = tmp1; prepre = tmp2; } return res; }};4.矩形覆盖题⽬描述:我们可以⽤2*1的⼩矩形横着或者竖着去覆盖更⼤的矩形。