凸n边形的三角形划分

问题:给定凸n边形P={1,2…,n},每一个顶点i带一个权数r(i)(i=1,2,…,n)。要求在该凸边形的顶点间连n-3条互不相交的连线,把凸边形分成n-2个三角形,每一个三角形的值为其他三个顶点权数之和。

解决过程:

(1)建立递推关系:

   设m(i,j)是求多边形MiMi+1…Mj划分的最小值,则有递推关系:

    m(i,i+2)=r(i)r(i+1)r(i+2)(j=i+2时,即三角形MiMi+1Mi+2)

    m(i,j)=min(m(i,k)+m(k,j)+r(i)r(k)r(j)(i<k<j)

   初始(边界)条件为m(i,i+1)=0(不构成三角形)

   显然,m(1,n)为最优值。

(2)求最优值的递推结构:

   当i<k<j且要求m(i,j)时,要用到m(i,k)和m(k,j)。为此,设置以下循环:

   for(d=2;d<=n-1;d++)

   for(i=1;i<=n-d;i++)

        j=i+d;

   这样,可按d从2开始递增取值,先得m(i,k)与m(k,j),为比较进而求m(i,j)提供可能。

(3)构造最优解

   设置s(i,j),在递推赋值时记录最优划分点k。注意到分划线分布为二叉结构,应用s(i,j)定义实现最优解的递归函数        f(a,b):

    a:设置c=s(a,b)记录参数a和b的最优分化点。

    b:若c>a+1,则输出a~c;

    c:若c<b-1,则输出c~b;

    d:然后调用下一层递归函数f(a,c)和f(c,b)。

   

#include<stdio.h>
int p,s[100][100];
main()
{
	int d,n,i,j,k,r[100];
	long t,m[100][100];
	void f(int x,int y);
	printf(" 请输入n:");
	scanf("%d",&n);
	printf(" 凸%d边形从第一点开始,依次输入各点权数:\n",n);
	for(i=1;i<=n;i++)
	{
		printf(" 请输入第%d个顶点的权数:",i);
		scanf("%d",&r[i]);
	}
	for(i=1;i<=n-1;i++) m[i][i+1]=0;
	for(d=2;d<=n-1;d++)
	for(i=1;i<=n-d;i++)
	{
		j=i+d;
		m[i][j]=100000000;
		for(k=i+1;k<j;k++)
		{
			t=m[i][k]+m[k][j]+r[i]*r[k]*r[j];
			if(t<m[i][j])
			{
				m[i][j]=t;
				s[i][j]=k;
			}
		}
	}
	p=0;
	printf("\n 最优%d条划分线分别为:\n",n-3);
	f(1,n);
	printf("\n 凸%d边形的三角形划分最小值为:%ld \n",n,m[1][n]);
}
#include<stdio.h>
void f(int a,int b)
{
	int c;
	if(b>a+1)
	{
		c=s[a][b];
		if(c>a+1)
		{
			p++;
			printf("  %2d--%2d;",a,c);
			if(p%6==0) printf("\n");
		}
		if(c<b-1)
		{
			p++;
			printf("  %2d--%2d;",c,b);
			if(p%6==0) printf("\n");
		}
		f(a,c);f(c,b);
	}
	return;
}

点赞