动态规划DP算法理解

1. DP算法定义:

每次决策依赖于当前状态,又随即引起状态的转移,多阶段最优化决策解决问题的过程就称为动态规划。

2. DP算法基本流程:

初始状态→│决策1│→│决策2│→…→│决策n│→结束状态

1、划分:按照问题的特征,把问题分为若干阶段。注意:划分后的阶段一定是有序的或者可排序的

2、确定状态和状态变量:将问题发展到各个阶段时所处的各种不同的客观情况表现出来。状态的选择要满足无后续性

3、确定决策并写出状态转移方程:状态转移就是根据上一阶段的决策和状态来导出本阶段的状态。根据相邻两个阶段状态之间的联系来确定决策方法和状态转移方程

4、边界条件:状态转移方程是一个递推式,因此需要找到递推终止的条件

DP算法实现三要素:

1、问题的阶段

2、每个阶段的状态

3、相邻两个阶段之间的递推关系

确定了动态规划的这三要素,整个求解过程就可以用一个最优决策表来描述,最优决策表是一个二维表,其中行表示决策的阶段,列表示问题状态,表格需要填写的数据一般对应此问题的在某个阶段某个状态下的最优值(如最短路径,最长公共子序列,最大价值等),填表的过程就是根据递推关系,从1行1列开始,以行或者列优先的顺序,依次填写表格,最后根据整个表格的数据通过简单的取舍或者运算求得问题的最优解。

例如:f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}

3. DP常见问题:

1、找零钱问题   

   有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。

测试样例:
penny=[1,2,4]

penny_size=3

aim = 3
返回:2
即:方案为{1,1,1}和{1,2}两种

分析:

  设dp[n][m]为使用前n中货币凑成的m的种数,那么就会有两种情况:

              使用第n种货币:dp[n-1][m]+dp[n-1][m-peney[n]]

              不用第n种货币:dp[n-1][m],为什么不使用第n种货币呢,因为penney[n]>m。

       这样就可以求出当m>=penney[n]时 dp[n][m] = dp[n-1][m]+dp[n][m-peney[n]],

  否则,dp[n][m] = dp[n-1][m]。

import java.util.*;  
public class Exchange {  
    public int countWays(int[] penny, int n, int aim) {  
        // write code here  
        if(n==0||penny==null||aim<0){  
         return 0;     
        }  
        int[][] pd = new int[n][aim+1];  
        for(int i=0;i<n;i++){  
         pd[i][0] = 1;     
        }  
        for(int i=1;penny[0]*i<=aim;i++){  
         pd[0][penny[0]*i] = 1;     
        }  
        for(int i=1;i<n;i++){  
            for(int j=0;j<=aim;j++){  
                if(j>=penny[i]){  
                    pd[i][j] = pd[i-1][j]+pd[i][j-penny[i]];  
                }else{  
                    pd[i][j] = pd[i-1][j];  
                }  
            }  
        }  
        return pd[n-1][aim];  
    }

2、走方格问题

      有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
给定一个矩阵map及它的行数n和列数m,请返回最小路径和。保证行列数均小于等于100.
测试样例:
[[1,2,3],[1,1,1]],2,3
返回:4

解析:设dp[n][m]为走到n*m位置的路径长度,那么显而易见dp[n][m] = min(dp[n-1][m],dp[n][m-1]);

import java.util.*;    
public class MinimumPath {  
    public int getMin(int[][] map, int n, int m) {  
        // write code here  
       int[][] dp = new int[n][m];  
        for(int i=0;i<n;i++){  
            for(int j=0;j<=i;j++){  
             dp[i][0]+=map[j][0];      
            }  
        }  
        for(int i=0;i<m;i++){  
            for(int j=0;j<=i;j++){  
             dp[0][i]+=map[0][j];      
            }  
        }  
        for(int i=1;i<n;i++){  
            for(int j=1;j<m;j++){  
             dp[i][j] = min(dp[i][j-1]+map[i][j],dp[i-1][j]+map[i][j]);     
            }  
        }  
        return dp[n-1][m-1];  
    }  
    public int min(int a,int b){  
        if(a>b){  
         return b;     
        }else{  
         return a;     
        }  
    }

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
路径规划问题可以使用动态规划模型来解决。动态规划是一种通过将问题分解为子问题并使用子问题的解来构建整体解的算法设计方法。 在路径规划中,我们可以将地图表示为一个有向图,其中节点表示位置,边表示路径。动态规划可以通过以下步骤进行: 1. 定义状态:我们需要定义状态来描述问题的子结构。在路径规划中,可以使用一个二维数组来表示状态,其中数组的行代表节点,列代表到达该节点的最短路径的其他节点。 2. 定义初始状态:我们需要定义问题的初始状态。在路径规划中,初始状态是起始节点。我们可以将起始节点的最短路径长度设置为0,其他节点的最短路径长度设置为无穷大。 3. 状态转移方程:我们需要定义状态之间的转移关系。在路径规划中,可以使用以下公式计算节点之间的最短路径长度: dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]) 其中dp[i][j]表示从节点i到节点j的最短路径长度,k表示其他节点。 4. 计算最优解:根据状态转移方程,我们可以使用动态规划算法计算出所有节点之间的最短路径长度。 5. 回溯路径:根据最短路径长度,我们可以回溯路径,找到从起始节点到目标节点的最短路径。 需要注意的是,动态规划适用于有向无环图(DAG),在存在环路的情况下,需要进行适当的处理。 这是一种基本的路径规划动态规划模型,具体的实现还需要根据具体的问题细节进行调整和优化。希望这个回答能帮到你!如果有更多问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值