算法!凸多边形最优三角剖分!请高手帮忙!

hnbalp 2008-10-12 09:53:49
有关“凸多边形最优三角剖分的问题”,这是《计算机算法设计与分析》(王晓东编著 第三版)第三章“动态规划”中的一道例题,代码如下:
“Point.h”
class Point{
public:
int x;
int y;
};

"MWTri.cpp"
#include<iostream>
#include"math.h"
#include"Point.h"
using namespace std;

#define MAX 100

int t[MAX][MAX];
int s[MAX][MAX];

int w(Point pt1,Point pt2,Point pt3){

int d1=(int)sqrt((pt2.y-pt1.y)*(pt2.y-pt1.y)+(pt2.x-pt1.x)*(pt2.x-pt1.x));
int d2=(int)sqrt((pt3.y-pt1.y)*(pt3.y-pt1.y)+(pt3.x-pt1.x)*(pt3.x-pt1.x));
int d3=(int)sqrt((pt3.y-pt2.y)*(pt3.y-pt2.y)+(pt3.x-pt2.x)*(pt3.x-pt2.x));
return d1+d2+d3;
}

void MinWeightTriangulation(Point * point,int n,int t[][MAX],int s[][MAX]){

for(int i=1;i<=n;i++) t[i][i]=0;
for(int r=2;r<=n;r++)
for(int i=1;i<=n-r+1;i++){
int j=i+r-1;
t[i][j]=t[i+1][j]+w(point[i-1],point[i],point[j]);
s[i][j]=i;
for(int k=i+1;k<j;k++){
int u=t[i][k]+t[k+1][j]+w(point[i-1],point[k],point[j]);
if(u<t[i][j]){

t[i][j]=u;
s[i][j]=k;
}
}
}

}

void main(){

Point pt[5];
pt[0].x=4;
pt[0].y=1;
pt[1].x=3;
pt[1].y=2;
pt[2].x=2;
pt[2].y=2;
pt[3].x=1;
pt[3].y=1;
pt[4].x=1;
pt[4].y=0;
//pt[5].x=4;
//pt[5].y=1;

/*for(int m=1;m<=4;m++)
for(int n=1;n<=4;n++)
s[m][n]=0;*/

MinWeightTriangulation(pt,4,t,s);
for(int m=1;m<=4;m++)
for(int n=1;n<=4;n++)
cout<<m<<" "<<n<<" "<<s[m][n]<<endl;




}




程序运行结果如下:

1 1 0
1 2 1
1 3 1
1 4 1
2 1 0
2 2 0
2 3 2
2 4 2
3 1 0
3 2 0
3 3 0
3 4 3
4 1 0
4 2 0
4 3 0
4 4 0
Press any key to continue

最后在构造最优解的时候,根据书中所述的“s[i][j]记录了Vi-1和Vj一起构成三角形的第3个顶点的位置。”,然后再根据最后的各个s[i][j]的值,再构造三角形时,在凸多边形内会有弦相交。
是我将算法生成代码的过程中出现了问题呢,还是根据s[i][j]来构造三角时出了问题?
请帮忙,多谢!

...全文
1614 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zzutom 2008-11-07
  • 打赏
  • 举报
回复
暂无答案,准备结贴,多谢大家~~
frisky_lobo 2008-10-18
  • 打赏
  • 举报
回复
时间真充裕啊
帅得不敢出门 2008-10-18
  • 打赏
  • 举报
回复
up
OutIT人 2008-10-17
  • 打赏
  • 举报
回复
mark ..
glacier3d 2008-10-17
  • 打赏
  • 举报
回复
动态规划问题,
组合数学生成函数法求解几何问题是也有类似剖分问题
baihacker 2008-10-12
  • 打赏
  • 举报
回复
#include	"windows.h"
#include <iostream>
using namespace std;

/*
问题描述:
把多边形0,...,n-1剖分成n-2个三角形,求给定的权值最小
本程序定义权为:剖分弦的长度和
程序功能:
用两种方法求解上述问题(针对任意权的和针对本问题的)
解法本质都是动态规划
PS :
动态规划很难,本程序难免会有错误,但是基本思路是正确的
注释得很详细了
*/

const V = 5;//5个顶点

void LoadData(float dist[][V]);
/*
解法1:
重新定义权为:剖分弦的长度和加上多边形的周长(显然等价),重新求解
本函数还适用于任何定义在剖分后的三角形上的权的情况(修改一下)
例如权为三角形的面积的面积平方和
*/
void minWeightTriangulation1(int n, float dist[][V], float t[][V], int s[][V]);
void ShowSolution1(int s[][V], int i, int j);

/*
解法2:
针对此问题的求解方法,不具有普遍适用性
*/
void minWeightTriangulation2(int n, float dist[][V], float t[][V+1], int s[][V+1]);
void ShowSolution2(int s[][V+1], int i, int j);

void end();

int main()
{
float dist[V][V];

float t1[V][V];
int s1[V][V];

float t2[V+1][V+1];
int s2[V+1][V+1];

LoadData(dist);

minWeightTriangulation1(V, dist, t1, s1);
cout<<"最优剖分权:"<<t1[1][4] - 2 - 1.414 * 3<<"\t剖分弦:\t";//要减去周长
ShowSolution1(s1, 1, 4);
cout<<endl;

minWeightTriangulation2(V, dist, t2, s2);
cout<<"最优剖分权:"<<t2[0][5]<<"\t剖分弦:\t";
ShowSolution2(s2, 0, 5);
cout<<endl;


return 0;
}

void LoadData(float dist[][V])
{
dist[0][1] = dist[1][0] = 1;
dist[1][2] = dist[2][1] = 1;
dist[2][3] = dist[3][2] = 1.414;
dist[3][4] = dist[4][3] = 1.414;
dist[4][0] = dist[0][4] = 1.414;
dist[0][2] = dist[2][0] = 1.414;
dist[0][3] = dist[3][0] = 2;
dist[1][3] = dist[3][1] = 2.236;
dist[1][4] = dist[4][1] = 2.828;
dist[2][4] = dist[4][2] = 2;
}

float Weight(float dist[][V], int i, int j, int k)
{
return dist[i][j] + dist[j][k] + dist [k][i];
}

void minWeightTriangulation1(int n, float dist[][V], float t[][V], int s[][V])
{
/*
t[i][j]表示顶点为i-1,i,...,j的多边形的最优三角剖分值
s[i][j]表示顶点为i-1,i,...,j的多边形的最优三角剖分方法,剖分点为s[i][j]
退化情况1:s[i][j]==i 剖分成 三角形i-1,i,j 和 多边形i,...,j
退化情况2:s[i][j]==j-1 剖分成 多边形i-1,...,j-1和 三角形i-1,j-1,j
一般情况:k = s[i][j] 剖分成 多边形i-1,...,k 和 多边形 k,...,j
权的定义:多边形的周长+剖分的弦长,所以对两种特殊情况进行了处理
*/
for (int i = 1; i < n; i++)
t[i][i] = 0;//只有两个顶点认为权是0
for (int r = 2; r < n; r++)//r+1边形
{
for (i = 1; i <= n - r; i++)
{
int j = i + r -1;
/*当i-1,i,j是相邻三个顶点时(r==2),权为
t[i+1][j] + Weight(dist, i-1, i, j)
否则,权为
t[i+1][j] + Weight(dist, i-1, i, j) - dist[i][j]
因为t[i+1][j]和eight(dist, i-1, i, j)分别计算了
一次dist[i][j]
*/
t[i][j] = t[i+1][j] + Weight(dist, i-1, i, j) -
(r==2?0:dist[i][j]);
s[i][j] = i;

for (int k = i + 1; k < j; k++)
{/*
当取剖分i-1,j-1时权为
t[i][k] + t[k+1][j] + dist[i-1][j] + dist[k][j]
因为t[k+1][j]退化,权为0,故把边dist[k][j]补上
否则权为t[i][k] + t[k+1][j] + dist[i-1][j]
*/
float u = t[i][k] + t[k+1][j] + dist[i-1][j] +
(k+1==j?dist[k][j]:0);
if (u<t[i][j])
{
t[i][j] = u;
s[i][j] = k;
}
}
}
}
}

void ShowSolution1(int s[][V], int i, int j)
{
if (i + 1 >= j) return;
int k = s[i][j];

if (k == i)
{//退化情况1:s[i][j]==i 剖分成 三角形i-1,i,j 和 多边形i,...,j
cout<<'('<<i<<','<<j<<") ";
ShowSolution1(s, i+1, j);
}
else
if (k==j-1)
{//退化情况2:s[i][j]==j-1 剖分成 多边形i-1,...,j-1和 三角形i-1,j-1,j
ShowSolution1(s, i, j-1);
cout<<'('<<i-1<<','<<j-1<<") ";
}
else
{//一般情况:k = s[i][j] 剖分成 多边形i-1,...,k 和 多边形 k,...,j
ShowSolution1(s, i, k);
cout<<'('<<i-1<<','<<k<<") ";
cout<<'('<<k<<','<<j<<") ";
ShowSolution1(s, k+1, j);
}
}

float Distance(float dist[][V], int i, int j)
{
if (i == (j + 1)%V || j == (i +1)%V)
return 0;
return dist[i][j];
}

void minWeightTriangulation2(int n, float dist[][V], float t[][V+1], int s[][V+1])
{
/*
t[i][j]表示从顶点i开始的j个顶点围成的多边形(j边形)的最优剖分的权
s[i][j]表示从顶点i开始的j个顶点围成的多边形(j边形)的最优剖分的方法,
剖分点为 i + s[i][j]
退化情况1:s[i][j]==1 剖分成 三角形i,i+1,i+j-1 和 多边形 i+1,...,i+j-1
退化情况2:s[i][j]==j-2剖分成 多边形i,...,i+j-2 和 三角形 i,i+j-2,i+j-1
一般情况 :k = s[i][j] 剖分成 多边形i,...,i+k 和 多边形 i+k,...,i+j-1
*/
const MAX = 10000;
float temp, q;
int kk;

for (int k = 0; k < n; k++)
{
t[k][2] = 0;
t[k][3] = 0;
}

for (int r = 4; r <= n; r++)
for (int i = 0; i < n; i++)
{
for (q = MAX, kk = 1; kk <= r - 2; kk++)
{/*
划分成子问题
多边形i,...,i+kk 和 多边形 i+kk,...,i+r-1
划分弦为 (i, ((i+kk)%n) 和 ((i+kk)%n, (i+r-1)%n)
由于Distance函数中相邻弦长度为0,故退化情况自动包含
*/
temp = t[i][(kk+1)%n] + t[(i+kk)%n][(n+r-kk)%n] +
Distance(dist, i, ((i+kk)%n) ) +
Distance(dist, (i+kk)%n, (i+r-1)%n);
if (temp < q)
{
k = kk;
q = temp;
}
}
t[i][r] = q;
s[i][r] = k;
if (r==n) break;//一旦r==n可以马上跳出本层循环
}
}

void ShowSolution2(int s[][V+1], int i, int j)
{
if (j<=3) return;

int k = s[i][j];
if (k==1)
{//退化情况1:s[i][j]==1 剖分成 三角形i,i+1,i+j-1 和 多边形 i+1,...,i+j-1
cout<<'('<<i+1<<','<<i+j-1<<") ";
ShowSolution2(s, i+1, j-1);
}
else
if (s[i][j]==j-1)
{//退化情况2:s[i][j]==j-2剖分成 多边形i,...,i+j-2 和 三角形 i,i+j-2,i+j-1
cout<<'('<<i<<','<<i+j-1<<") ";
ShowSolution2(s, i, j-1);
}
else
{//一般情况 :k = s[i][j] 剖分成 多边形i,...,i+k 和 多边形 i+k,...,i+j-1
ShowSolution2(s, i, k+1);
cout<<'('<<i<<','<<i+k<<") ";
ShowSolution2(s, i+k, j-k);
cout<<'('<<i+k<<','<<i+j-1<<") ";
}
}

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧