当前位置:   article > 正文

动态规划经典题目-最小权三角剖分_设a是顶点为1,2,…n的凸多边形,可以用不在内部相交的n-3条对角线将a划分成三角形,

设a是顶点为1,2,…n的凸多边形,可以用不在内部相交的n-3条对角线将a划分成三角形,

一、题目描述

设A是顶点为0,1,…,n-1的n凸多边形,可以用不在内部相交的n-3条对角线将A划分成三角形,如下图就是5边形的所有的划分方案.假设凸n边形的边及对角线的长度dij,都是给定的正整数,0≤i<j≤n-1.划分后三角形ijk的权值等于其周长,求具有最小权值的划分方案.设计一个动态规划算法求解这个问题,说明算法的时间复杂度.

在这里插入图片描述

示例1:

在这里插入图片描述

输入:d = [  
			[0,2,3,1,5,6],
			[2,0,3,4,8,6],
			[3,3,0,10,13,7],
			[1,4,10,0,12,5],
			[5,8,13,12,0,3],
			[6,6,7,5,3,0]
		  ]
输出:54
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

二、解题思路

1. 定义状态

在这里插入图片描述

​ 为了应用动态规划,我们需要将多边形切成小块.可以观察到,所输入的多边形每条边都肯定只能归属于一个三角形.将这条边要变为一个三角形意味着得确定第三个顶点,如上图所示.一旦我们找到正确的连接顶点,多边形的剩余部分就会被划分为两个小块,而这两块都需要进行最优的三角剖分.令dp[i][j]为从顶点vi到顶点vj进行三角剖分所需的费用,计入从vi到vj的弦长.递推式如下:

d p [ i ] [ j ] = m i n ( d p [ i ] [ k ] + d p [ k ] [ j ] + d i k + d k j + d i j ) dp[i][j] = min(dp[i][k] + dp[k][j] + d_{ik} + d_{kj} + d_{ij}) dp[i][j]=min(dp[i][k]+dp[k][j]+dik+dkj+dij)

2. 定义状态转移方程

  • 当j - i = 1时,有

d p [ i ] [ j ] = 0 dp[i][j] = 0 dp[i][j]=0

  • 当j - i > 1时,有

    d p [ i ] [ j ] = m i n ( d p [ i ] [ k ] + d p [ k ] [ j ] + d i k + d k j + d i j ) , i < k < j dp[i][j] = min(dp[i][k] + dp[k][j] + d_{ik} + d_{kj} + d_{ij}),i < k < j dp[i][j]=min(dp[i][k]+dp[k][j]+dik+dkj+dij),i<k<j

3. 初始化

​ 当j - i = 1时,有 d p [ i ] [ j ] = 0 dp[i][j] = 0 dp[i][j]=0

4. 计算方式

​ 自底向上,自左向右计算dp数组

三、代码实现

/**
 * 最小三角权剖分
 *
 *  @author hh
 *  @date 2021-5-24 23:35
 */
public class MinWeightTriangulation {

    public int minWeight(int[][] d){
        int[][] dp = new int[d.length][d[0].length];
        for(int i = d.length - 1; i >= 0; i--){
            for(int j = 0; j < d[0].length; j++){
                if(j - i == 1){
                    dp[i][j] = 0;
                    continue;
                }
                dp[i][j] = Integer.MAX_VALUE;
                for(int k = i + 1; k < j; k++){
                    dp[i][j] = Math.min(dp[i][j],dp[i][k] + dp[k][j] + d[i][k] + d[k][j] + d[i][j]);
                }
            }
        }
        return dp[0][d[0].length -1];
    }

    public static void main(String[] args){
        int[][] d = new int[][]{
                {0,2,3,1,5,6},
                {2,0,3,4,8,6},
                {3,3,0,10,13,7},
                {1,4,10,0,12,5},
                {5,8,13,12,0,3},
                {6,6,7,5,3,0}
        };
        MinWeightTriangulation minWeightTriangulation = new MinWeightTriangulation();
        System.out.println(minWeightTriangulation.minWeight(d));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

四、执行结果

在这里插入图片描述

五、思考

​ 本题和字符串切分、矩阵链乘法的做法非常相似,也是非常经典的,都是对dp数组进行线性划分,读者有时间可以看我的另一篇文章动态规划经典题目-字符串切分动态规划经典题目-矩阵链乘法,进行举一反三。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/670557
推荐阅读
相关标签
  

闽ICP备14008679号