凸多边形最优三角剖分问题

来源:互联网 发布:淘宝新品上架时间 编辑:程序博客网 时间:2024/05/01 11:47
 

/*
 * 多边形是平面上一条分段线形闭曲线。也就是说,多边形是由一系列首尾相接的直线段
 * 所组成的。组成多边形的各个直线段称为该多边形的边。连接多边形相继两条边的点称为
 * 多边形的顶点。当多边形边界上或者内部任意两点所连成的直线段上所有点都在多边形的
 * 内部或者边界上就叫凸多边形
 * 通常,凸多边形顶点的逆时针序列表示凸多边形,即P={v0,v1,...,vn-1}表示具有
 * n条边v0,v1,v2...vn-1,vn的凸多边形。其中,约定v0=vn
 * 多边形的三角剖分是将多边形分割成互不相交的三角形的弦的集合T。在有n个顶点的多边形
 * 的三角剖分中,恰好有n-3条弦和n-2个三角形。
 * 凸多边形的最优三角剖分问题:给定凸多边形P={v0,v1,v2...vn},以及定义在由多
 * 边形的边和弦组成的三角形的权函数w。要求确定该凸多边形的三角剖分,使得该三角剖分
 * 所对应的权,即该三角剖分中诸三角形上权之和最小。
 * 在本文中,设定权函数w(vi,vj,vk)=|vivj|+|vjvk|+|vkvi|
 * 凸多边形的最优三角剖分具有最优子结构性质。
 * 事实上,若凸(n+1)边形P={v0,vi,...vn}的最优三角剖分T包含三角形v0vkvn,则T的权
 * 为三个权值 部分的和。可以断言,由T所确定的这两个子多边形的三角剖分也是最优的。因为
 * 若有{v0,v1,...vk}或{vk,vk+1...vn}的更小权的三角剖分将导致T不是最优的三角形剖分。
 * 最优三角部分的递归结构:
 * 首先:定义t[i][j],1<=i<=n为凸多边形{vi-1,vi,...vj}的最优三角剖分所对应的函数权
 * 值,即其最优值。为简化期间,设退化的多边形{vi-1vi}有权值0。据此定义,要计算凸多边形
 * 的权值为t[1][n].
 * t[i][j]的值可以由最优子结构性质递归地计算。由于退化的2顶点多边形的权值为0,所以t[i][i]
 * =0,i=1,2,...n.当j-i>=1时,凸子多边形{vi-1,vi,...vj}至少有三个顶点。由最优子结构
 * 的定义,t[i][j]的值应该为t[i][k]+t[k][j]+w(vi-1,vk,vj).而j的所有可能的位置只
 * 有j-i个。因此,可以递归的定义为:
 *          0
 * t[i][j]={
 *           min{t[i][k]+t[k+1][j]+w(vi-1vkvj),i<=k<j}
 *
 */     
package dynamic_progranmming;

/**
 * @author wangzhendong
 *
 */
public class MinWeightTriangulation {
 /*
  * 私有变量
  */
 private  double[][] t;//存放代价
 private  int[][] s;//记录于i-1,j一起的三角形顶点的位置
 private  int num;//多边形顶点个数
    //private  double[] X;//每个顶点的横坐标
    //private  double[] Y;//每个顶点的纵坐标
    private  double[][][] w;//每两个顶点的连接代价
 /*
  * 构造函数
  */
 public MinWeightTriangulation(double[][][] w,int num) {
  // TODO Auto-generated constructor stub
  t=new double[num+1][num+1];
  s=new int[num+1][num+1];
  this.num=num;
  this.w=w;
 }
 /*
  * 使用动态规划方法来解决问题
  */
     public void minWeightTriangulation()
     {
      for(int i=1;i<=num;i++)
      {
       t[i][i]=0;
      }
      for(int r=2;r<=num;r++)
      {
       for(int i=1;i<=num-r+1;i++)
       {
        int j=i+r-1;
        t[i][j]=t[i+1][j]+w[i-1][i][j];
        s[i][j]=i;
        for(int k=i+1;k<i+r-1;k++)
        {
         double u=t[i][k]+t[k+1][j]+w[i-1][k][j];
         if(u<t[i][j])
         {
          t[i][j]=u;
          s[i][j]=k;
         }
        }
       }
      }
      System.out.println(t[1][num]);
      for(int i=0;i<=num;i++)
      {
       for(int j=i+1;j<=num;j++)
       {
        System.out.print(i+"  "+j+"  "+s[i][j]);
        System.out.println();
       }
      }
 
     }
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
        double[] X={0,3,4,7,6,15,17,20,35,37};
        double[] Y={0,7,8,10,6,0,-4,-6,-6,-4};
        double[][][] w=new double[11][11][11];
        for(int i=0;i<11;i++)
        {
         for(int j=0;j<11;j++)
         {
          for(int k=0;k<11;k++)
          {
           w[i][j][k]=Math.sqrt(Math.pow(X[i%10]-X[j%10],2)+Math.pow(Y[i%10]-Y[j%10],2))+Math.sqrt(Math.pow(X[i%10]-X[k%10],2)+Math.pow(Y[i%10]-Y[k%10],2))+Math.sqrt(Math.pow(X[k%10]-X[j%10],2)+Math.pow(Y[k%10]-Y[j%10],2));
          }
         }
        }
        MinWeightTriangulation mwt=new MinWeightTriangulation(w,10);
        mwt.minWeightTriangulation();
       
 }

}

 


最后测试输出:

256.4967293375141
0  1  0
0  2  0
0  3  0
0  4  0
0  5  0
0  6  0
0  7  0
0  8  0
0  9  0
0  10  0
1  2  1
1  3  1
1  4  1
1  5  4
1  6  4
1  7  5
1  8  5
1  9  7
1  10  1
2  3  2
2  4  2
2  5  4
2  6  5
2  7  5
2  8  5
2  9  7
2  10  4
3  4  3
3  5  4
3  6  5
3  7  5
3  8  5
3  9  7
3  10  4
4  5  4
4  6  5
4  7  5
4  8  7
4  9  7
4  10  4
5  6  5
5  7  5
5  8  7
5  9  7
5  10  5
6  7  6
6  8  7
6  9  7
6  10  7
7  8  7
7  9  7
7  10  9
8  9  8
8  10  9
9  10  9

原创粉丝点击