算法设计: 三、动态规划 (2. 多段图问题)—— java实现 - 算法分析

一、动态规划思想

把待求解问题分解成若干个子问题,先求解子问题,
然后由这些子问题的解得到原问题的解,但动态规划求解过的子问题的结果会
被保留下来,不像递归那样每个子问题的求解都要从头开始返回求解。动态规
划求解问题的关键在于获得各个阶段子问题的递推关系式:

  1. 分析原问题的最优解性质,刻画其结构特征
  2. 递归定义最优值
  3. 自底向上(由后向前)的方式计算最优值
  4. 根据计算最优值时得到的信息,构造一个最优解。

1、动态规划的最优决策原理

活动过程划分为若干个阶段,每一阶段的决策,依赖于前一阶段的状态,由决策所采取的动作,使状态发生转移,成为下一阶段的决策依据。

图6.1 动态规划的决策过程
最优性原理:无论过程的初始状态和初始决策是什么,其余决策都必须相对于初始决策所产生的状态,构成一个最优决策序列。

令最优状态为 ,由此倒推:

最优决策序列,
状态转移序列:
赖以决策的策略或目标,称为动态规划函数。
整个决策过程,可以递归地进行,或用循环迭代的方法进行。
动态规划函数可以递归地定义,也可以用递推公式来表达。
最优决策是在最后阶段形成的,然后向前倒推,直到初始阶段;
而决策的具体结果及所产生的状态转移,却是由初始阶段开始进行计算的,然后向后递归或迭代,直到最终结果。

二、多段图问题

若存在一个有向加权图 G,且 G 能分出起点和终点以及中间的 n 的阶段,求起
点到终点的最短(长)距离。

1、多段图动态规划算法思想

  1. 将图中的顶点划分 5 个阶段,k
  2. 每个阶段有几种供选择的点 s
  3. 当前状态应在前一个状态的基础上获得。决策需要满足规划方程
  4. 规划方程:f(k)表示状态 k 到终点状态的最短距离。
    初始条件:f(k)=0,k=0;
    f(k-1)=min{f(k)+W(k-1,k)}其中 W(k-1,k)表示状态 k-1 到状态 k 的距离
    在这里插入图片描述

2、多段图动态规划算法 源码:

  public class MinDistance {
      static int N=13;   //结点个数,从1开始
      static int K=5;    //阶段数量,从1
      static int MAX=1000;   //定义一个最大值,用于初始化
      static int[][] c=new int[N][N];			//c[i][j]表示i到j的花费
      static int[] cost=new int[N];		//cost[i]表示到结点i的最小花费
      static int[] d=new int[N];			//d[i]表示由结点i指向的最小成本边的另一端的结点
      static int[] p=new int[K];			//每一阶段最短路径
      public static void main(String[] args) {
 //------------------初始化数据------------------------
         for (int i = 1; i < N; i++)
    	{
    		cost[i] = 0;     
    		for (int j = 1; j < N; j++)
    		{
    			c[i][j] = MAX;
    		}
    	}
     	c[1][2] = 9;
     	c[1][3] = 7;
     	c[1][4] = 3;
     	c[1][5] = 2;
    	c[2][6] = 4;
    	c[2][7] = 2;
    	c[2][8] = 1; 
    	c[3][6] = 2;
    	c[3][7] = 7; 
    	c[4][8] = 11; 
    	c[5][7] = 11; 
    	c[5][8] = 8;
    	c[6][9] = 6; 
    	c[6][10] = 5; 
    	c[7][9] = 4; 
    	c[7][10] = 3;
    	c[8][10] = 5; 
    	c[8][11] = 6; 
    	c[9][12] = 4; 
    	c[10][12] = 2;
    	c[11][12] = 5;
    	fGraph();
    	int k = K;
    	int sum = 0;
    	int n = N - 1;
    	while (k != 1)//遍历每个阶段的最短路径成本
    	{
    		p[k-1]=n;
    		sum += cost[n];
    		n = d[n];
    		k--;	
    	}
        System.out.println("最短路径长度:"+sum);
        System.out.print("最短路径:1");
        for(int i=1;i<5;i++){
        	System.out.print("->"+p[i]);
        }
      }
      public static void fGraph()   //采用向前处理的方法
    	{
    		int min;
    		for (int j = N-1; j > 0; j--)
    		{
    			min = MAX;
    			for (int i = j; i > 0; i--)
    			{
    				if (c[i][j] != MAX && cost[j] + c[i][j] < min)
    				{
    					min = cost[i] + c[i][j];
    					d[j] = i;
    				}    			
    			}
    			cost[j] = min;//cost[j]保留到结点j的最短边的权值
    		}
    	}
 }

3、算法分析

时间复杂度:O(n+m)

10~13行的初始化,花费 O(n) 时间。
14~23行局部决策,假定图的边数为 ,则花费时间为 O(n+m)
24~28行形成最优决策序列,若多段图分为 k 段,花费 O(k) 时间。

空间复杂度:O(n)
  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
以下是Java实现动态规划算法,用于凸多边形的最优三角剖分: ```java public class Triangulation { public static double minWeightTriangulation(double[] vertices) { int n = vertices.length / 2; double[][] dp = new double[n][n]; for (int len = 2; len < n; len++) { for (int i = 0; i < n - len; i++) { int j = i + len; dp[i][j] = Double.MAX_VALUE; for (int k = i + 1; k < j; k++) { double weight = dp[i][k] + dp[k][j] + triangleArea(vertices, i, k, j); if (weight < dp[i][j]) { dp[i][j] = weight; } } } } return dp[0][n - 1]; } private static double triangleArea(double[] vertices, int i, int j, int k) { double x1 = vertices[2 * i]; double y1 = vertices[2 * i + 1]; double x2 = vertices[2 * j]; double y2 = vertices[2 * j + 1]; double x3 = vertices[2 * k]; double y3 = vertices[2 * k + 1]; return Math.abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0); } } ``` 这个算法中,`vertices`数组包含了多边形的所有顶点坐标,按照顺序存储,每个顶点有两个坐标值:x和y。`minWeightTriangulation`方法返回最优三角剖分的权重和,即所有三角形的面积之和。 算法的核心是一个二维数组`dp`,其中`dp[i][j]`表示从第i个顶点到第j个顶点的最优三角剖分的权重和。通过动态规划的方式,逐步计算出所有子问题的最优解,最终得到全局最优解。 具体来说,算法的外层循环枚举子问题的长度,从2开始,一直到n-1。内层循环枚举子问题的起点i和终点j,计算出所有可能的三角剖分方式,并选择其中权重和最小的一个。这个过程的时间复杂度是O(n^3),可以通过一些优化来降低复杂度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Whitemeen太白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值