双调欧几里得

参考 http://blog.sina.com.cn/s/blog_51cea4040100gkcq.html

 

二、

对所有的坐标按x递增排序,上图有7个点

假设d(i,j)是i点和j点的直线距离,p(i,j)是从i点到j点的最短双调欧几里得距离,那么我们可以得到p(i,j)=p(j,i),下面就i>=j的情况考虑,,假设点是1,2,....N

1. i==j  此时p(i,i)=p(i-1,i)+d(i-1,i)

2.j==i-1,此时在j之前有[1,j-1]个点, p(i,j)=min( p(j,k) +d(k,i) ),其中k>=1 && k<=j-1

3. j<i-1, 此时 p(i,j)=p(i-1,j)+d(i-1,i)

 

代码如下

#include<iostream>
#include<cmath>
#include<climits>
#include<iomanip>
using namespace std;

typedef struct xy{
	int x,y;
}Point;

#define  N 7


void dp()
{
	int i,j;
	Point* data=new Point[N+1];
	for(i=1;i<=N;i++)
		cin>>data[i].x>>data[i].y;
	
	double p[N+1][N+1]={0};
	double d[N+1][N+1]={0};

	for(i=1;i<=N;i++)
		for(j=1;j<=N;j++)
			d[i][j]=sqrt((data[i].x-data[j].x)*(data[i].x-data[j].x)+(data[i].y-data[j].y)*(data[i].y-data[j].y));
	
	

	p[1][2]=p[2][1]=sqrt((data[2].x-data[1].x)*(data[2].x-data[1].x)+(data[2].y-data[1].y)*(data[2].y-data[1].y));
	
		
	p[1][1]=0;
	for(i=2;i<=N;i++)
	{
		
	 	// i=j+1
		if(i==2)
			p[2][1]=p[1][2]=sqrt((data[2].x-data[1].x)*(data[2].x-data[1].x)+(data[2].y-data[1].y)*(data[2].y-data[1].y));
		else
			p[i][i-1]=INT_MAX;
		for(j=1;j<=i-2;j++)
		{
				double temp=p[i-1][j]+d[i][j];
				if(temp<p[i][i-1])
					p[i][i-1]=p[i-1][i]=temp;
		}

		//i>j+3
		for(j=1;j<=i-2;j++)
		{
			p[i][j]=p[i-1][j]+d[i][i-1];
			p[j][i]=p[i][j];
		}
		//i==j
		p[i][i]=p[i][i-1]+d[i][i-1];
	}
	
	/*
	for(i=1;i<=N;i++)
	{
		for(j=1;j<=N;j++)
			cout<<fixed<<cout.precision(2)<<p[i][j]<<" ";
		cout<<endl;
	}
	*/

	cout<<fixed<<p[7][7]<<endl;



	delete [] data;
}

int main()
{
	dp();
	return 0;
}

  测试数据

1 1

2 7

3 4

6 3

7 6

8 2

9 5

结果  25.584025

 

posted on 2013-06-19 16:47  紫金树下  阅读(372)  评论(0编辑  收藏  举报