转载说明:本文由 风仲达 原创,如有侵权立刻删除
1、问题相关定义:
(1)凸多边形的三角剖分:将凸多边形分割成互不相交的三角形的弦的集合T。
(2)最优剖分:给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w。要求确定该凸多边形的三角剖分,使得该三角剖分中诸三角形上权之和为最小。
凸多边形三角剖分如下图所示:
2、最优子结构性质:
若凸(n+1)边形P={V0,V1……Vn}的最优三角剖分T包含三角形V0VkVn,1<=k<=n,则T的权为三个部分权之和:三角形V0VkVn的权,多边形{V0,V1……Vk}的权和多边形{Vk,Vk+1……Vn}的权之和。如下图所示:
可以断言,由T确定的这两个子多边形的三角剖分也是最优的。因为若有{V0,V1……Vk}和{V0,V1……Vk}更小权的三角剖分,将导致T不是最优三角剖分的矛盾。因此,凸多边形的三角剖分问题具有最优子结构性质。
3、递推关系:
设t[i][j],1<=i<j<=n为凸多边形{Vi-1,Vi……Vj}的最优三角剖分所对应的权值函数值,即其最优值。最优剖分包含三角形Vi-1VkVj的权,子多边形{Vi-1,Vi……Vk}的权,子多边形{Vk,Vk+1……Vj}的权之和。
因此,可得递推关系式:
凸(n+1)边形P的最优权值为t[1][n]。
程序清单如下:
//3d5 凸多边形最优三角剖分
#include <iostream>
using namespace std;
const int N = 7;//凸多边形边数+1
int weight[][N] = {{0,2,2,3,1,4},{2,0,1,5,2,3},{2,1,0,2,1,4},{3,5,2,0,6,2},{1,2,1,6,0,1},{4,3,4,2,1,0}};//凸多边形的权
int MinWeightTriangulation(int n,int **t,int **s);
void Traceback(int i,int j,int **s);//构造最优解
int Weight(int a,int b,int c);//权函数
int main()
{
int **s = new int *[N];
int **t = new int *[N];
for(int i=0;i<N;i++)
{
s[i] = new int[N];
t[i] = new int[N];
}
cout<<"此多边形的最优三角剖分值为:"<<MinWeightTriangulation(N-1,t,s)<<endl;
cout<<"最优三角剖分结构为:"<<endl;
Traceback(1,5,s); //s[i][j]记录了Vi-1和Vj构成三角形的第3个顶点的位置
return 0;
}
int MinWeightTriangulation(int n,int **t,int **s)
{
for(int i=1; i<=n; i++)
{
t[i][i] = 0;
}
for(int r=2; r<=n; r++) //r为当前计算的链长(子问题规模)
{
for(int i=1; i<=n-r+1; i++)//n-r+1为最后一个r链的前边界
{
int j = i+r-1;//计算前边界为r,链长为r的链的后边界
t[i][j] = t[i+1][j] + Weight(i-1,i,j);//将链ij划分为A(i) * ( A[i+1:j] )这里实际上就是k=i
s[i][j] = i;
for(int k=i+1; k<j; k++)
{
//将链ij划分为( A[i:k] )* (A[k+1:j])
int u = t[i][k] + t[k+1][j] + Weight(i-1,k,j);
if(u<t[i][j])
{
t[i][j] = u;
s[i][j] = k;
}
}
}
}
return t[1][N-2];
}
void Traceback(int i,int j,int **s)
{
if(i==j) return;
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
cout<<"三角剖分顶点:V"<<i-1<<",V"<<j<<",V"<<s[i][j]<<endl;
}
int Weight(int a,int b,int c)
{
return weight[a][b] + weight[b][c] + weight[a][c];
}
程序输入如下所示:
运行结果如图:
第二个答案
转载说明:本文由 咚咚锵_光 原创,如有侵权立刻删除
一凸8边形P的顶点顺时针为 ,任意两顶点间的线段的权重由矩阵D给出。若 与 是P上不相邻的两个顶点,则线段 称为P的一条弦。求P得一个弦的集合T,使得T中多有的弦恰好将P分割成互不重迭的三角形,且各三角形的权重之和为最小(一个三角形的权重是其各边的权重之和)。
求解
解题思路:
第一步:首先需要确定一个事实,这是一个无向图,假设图有5个节点,当你考虑节点顺序2,3,5构成的划分时,你也同时考虑了节点5,2,3..的划分
也就是说,当你划分程序走到序号最大的节点n之后,就不必在走一个环路,走回节点1了,因为你已经考虑过及节点1到节点n之间的最佳划分,这同时也是节点n到节点1的最佳划分
第二步:其次,要明确一点,这题是一道动态规划的题目,计算过程是一个积少成多的过程
第三步:解题:
1、我们用D[i][j]表示从节点i一直到节点j的最优划分,用w(i,j,k)计算并表示由节点i,j,k构成的三角形边的总和。
2、可以证明,肯定存在两个拓扑顺序连续的点,外加另外一个点,将此凸多边形划分为三部分,左侧多边形D1,三角形w(i,i+1,k),右侧多边形D2
什么事拓扑顺序?可能在这里将其称为拓扑有失偏颇,但是,其性质确实有些类似,当你排出掉点i之后,i-1拓扑连续的下一个点就变成了i+1,如此理解应该可以明白
既然是动态规划,那必定有一个确定的递推公式,此题的递推公式如下:
F(i,j)=min{F(i,k)+F(k,j)+w(i,j,k)}
此公式就表示了上面解题2中阐述的事实
伪码:
//初始化
for i←0 to n-1
for l←3 to n
if k
Out Put D[SIZE][SIZE]
D[0][SIZE-1] is the final result
有一点需要解释,这是动态规划,因此,当你划分1~7构成的多边形时,1~6,2~7都是已经划分好的
有人或许会问,为什么没有3,4,5,6,7,1这样的节点集合呢?
题目的解题思路是这样的,以<1,7>为底边,让顶点在2~6之间移动,必定存在一个点,构成三角形w(1,k,7)属于最优三角划分,因为<1,7>肯定是划分中的一条边。
寻到k之后,边<1,7>被排除,区域被划分为1~k和k~7,彼此之间不再有交集,因此不存在回路。
而后分别以边<1,k>,为底边,分别在顶点集2~k-1和k+1~6之间寻找下一个最优化分。
这里可以参考一下并查集的思路,这里其实是逆着并查集的思想不断深入的。好好思考!
因此也就不存在类如3,4,5,6,7,1的划分方式
实际测试代码
//代码、
#include
#define SIZE 8
using namespace std;
const int weight[8][8]={
};
int w(int x,int y,int z){
}
int main(){
//个三角行划分
if(l!=3){
if(k
}
谨以此为备忘,读者有不明白的地方请留言,嘿嘿