赞
踩
假期 2020.01.15
这篇博文花了我挺多时间的...,到今天才算近似完全弄懂,虽然有参考书籍...。
博文内容有所参考书籍《趣学算法》
凸多边形的三角剖分:将凸多边形分割成互不相交的三角形的弦的集合T。
最优剖分:给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w。要求确定该凸多边形的三角剖分,使得该三角剖分中诸三角形上权之和为最小。
如下图的划分第一幅图:从V3开始的划分,有{v1v3,v3v0,v3v6,v4v6};从V1开始的划分,有{v1v3,v1v4,v4v6,v1v6};这就是两种形式的划分。而我们的目的是找到划分中的边的权值之和最小,即最优剖分。
(以下图片引用于百度图片,点击了解详情)
该问题属于动态规划问题,首先,我们明确着手点在在于开始的时候定一个点v0为划分的起点,Vn为终点,那么如图如果定Vk为目前最优划分点,那么原问题就划分为两个子问题和一个三角形的问题,子问题分别是{V0,V1,V2,V3,…,Vk}和{Vk,…,Vn},三角形为V0VkVn,如下图所示:
weight[ i ][ j ] = weight[ i ][ k ] + weight[k + 1][ j ] + w{V(i-1),Vk,Vj}, i < j;
weight[ i ][ j ] = 0, i = j;
递归关系式解析:
weight[ i ][ k ]表示子问题{V(i-1),Vi,V(i+1),…,Vk};
weight[k + 1][ j ] 表示子问题{V(k),Vi,V(i+1),…,V(j-1)};
w{V(i-1),Vk,Vj}表示三角形的权值;
注意: 在循环结构中,三角形的查找是根据由小的三角形逐渐扩展到大的三角形,就可以找到最优的三角形。即子问题重叠问题:
子问题重叠性质
子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。
动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的解题效率。显然凸多边形的最优三角划分具有子问题重叠性质,如下图(图片引用于百度文库):
图解分析
#include<iostream> #include<algorithm> using namespace std; const int Max = 1000 + 5; int Result[Max][Max];//最优选择方案 double Weight[Max][Max], Map[Max][Max];//辅助数组,顶点连接权值 void C_Input(int C_Vertex);//s输入函数 void C_print(int n, int C_Vertex);//输出函数 void Search_triangulation(int C_Vertex);//寻找最优值函数 int main() { int C_Vertex; cout << "请输入顶点得个数"<<endl; cin >> C_Vertex; C_Vertex = C_Vertex - 1; cout << "请输入各顶点的连接权值" << endl; C_Input(C_Vertex); Search_triangulation(C_Vertex); cout << "最优值是"; cout << Weight[1][C_Vertex]; cout << endl; C_print(1, C_Vertex); return 0; } void Search_triangulation(int C_Vertex) { /*初始化数组*/ for (int i = 0; i <= C_Vertex; i++) for (int j = 0; j <= C_Vertex; j++) { Weight[i][j] = 0; Result[i][j] = 0; } for (int scale = 2; scale <= C_Vertex; scale++)//至少两个端点 { for (int i = 1; i <= C_Vertex - scale + 1; i++)//从1开始保证至少为三角形 { int j = i + scale - 1;//计算临时终点 /*当 i == k 时的处理 */ Weight[i][j] = Weight[i + 1][j] + Map[i - 1][j] + Map[i - 1][i] + Map[i][j]; /*分割起始点*/ Result[i][j] = i; for (int k = i + 1; k < j; k++) { double temp = Weight[i][k] + Weight[k + 1][j] + Map[i - 1][k] + Map[k][j] + Map[i - 1][j]; if (Weight[i][j] > temp) { Result[i][j] = k; Weight[i][j] = temp; } } } } return; } void C_Input(int C_Vertex) { int i, j; for(i = 0;i <= C_Vertex;i++) for(j = 0;j <= C_Vertex;j++) cin>> Map[i][j]; return ; } void C_print(int i, int j) { if (i == j) return; if (Result[i][j] > i) cout << "{v" << i - 1 << "v" << Result[i][j] << "}" << endl; if (j > Result[i][j] + 1) cout << "{v" << Result[i][j] <<"v"<<j<<"}" << endl; C_print(i, Result[i][j]); C_print(Result[i][j] + 1,j); return; }
请输入顶点得个数
6
请输入各顶点的连接权值
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
{v0v3}
{v3v5}
{v0v2}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。