poj1556---計算幾何+最短路

//這道題就是麻煩了點,其他都很簡單,細節問題。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define PR 1e-8
#define N 10005
double edge[N][N];
double dis[N];
bool vis[N];
struct TPoint
{
	double x,y;
	TPoint(){}
	TPoint(double _x,double _y):x(_x),y(_y){}
	TPoint operator-(const TPoint p) {return TPoint(x-p.x,y-p.y);}
};
struct TSeg
{
	TPoint st[2];
	TSeg(){}
	TSeg(TPoint a,TPoint b){st[0]=a,st[1]=b;}
}g;
struct TDoor
{
	TSeg d[2];
}door[N];
int n,m;
int dblcmp(double a) {return fabs(a)<PR?0:a>0?1:-1;}
double cross(TPoint a,TPoint b,TPoint c)
{
	TPoint s(b-a),t(c-a);
	return s.x*t.y-s.y*t.x;
}
double dot(TPoint a,TPoint b,TPoint c)
{
	TPoint s(b-a),t(c-a);
	return s.x*t.x+s.y*t.y;
}
int betweencmp(TPoint a,TPoint b,TPoint c)
{
	return dblcmp(dot(a,b,c));
}
double dist(TPoint a,TPoint b)
{
	TPoint s(b-a);
	return sqrt(s.x*s.x+s.y*s.y);
}
bool segcross(TSeg a,TSeg b)//線段判交
{
	double s1,s2,s3,s4;
	int d1,d2,d3,d4,l=0;
	d1=dblcmp(s1=cross(a.st[0],b.st[0],b.st[1]));//叉積
	d2=dblcmp(s2=cross(a.st[1],b.st[0],b.st[1]));
	d3=dblcmp(s3=cross(b.st[0],a.st[0],a.st[1]));
	d4=dblcmp(s4=cross(b.st[1],a.st[0],a.st[1]));
	if((d1^d2)==-2&&(d3^d4)==-2)//標準相交,返回交點
		return 1;
	if(d3==0&&(betweencmp(a.st[0],b.st[0],b.st[1])<=0))//a.s在線b上
		return 1;
	if(d4==0&&(betweencmp(a.st[1],b.st[0],b.st[1])<=0))//a.e在線b上
		return 1;
	if(d1==0&&(betweencmp(b.st[0],a.st[0],a.st[1])<=0))//b.s在線a上
		return 1;
	if(d2==0&&(betweencmp(b.st[1],a.st[0],a.st[1])<=0))//b.e在線a上
		return 1;
	return 0;
}
void getedge()
{
	int i,j,k,i1,i2,j1,j2;
	bool tmp;
	for(i=1;i<=n+1;i++)
		for(j=0;j<i;j++)
			for(i1=0;i1<2;i1++)
				for(j1=0;j1<2;j1++)
					for(i2=0;i2<2;i2++)
						for(j2=0;j2<2;j2++)
						{
							tmp=false;
							for(k=j+1;k<i;k++)
							{
								g.st[0]=door[j].d[j1].st[j2];
								g.st[1]=door[i].d[i1].st[i2];
						    	if(!(segcross(g,door[k].d[0]))
									&&!(segcross(g,door[k].d[1])))
								{tmp=true;break;}
							}
							if(!tmp)
					    		if(j==0) edge[j][4*i-2*i1-i2]=dist(door[j].d[j1].st[j2],door[i].d[i1].st[i2]);
								else edge[4*j-2*j1-j2][4*i-2*i1-i2]=dist(door[j].d[j1].st[j2],door[i].d[i1].st[i2]);
						}
}
void dijkstra(int u,int v)
{
	int i,j,k;
	n=4*n+1;
	for(i=0;i<=n;i++)
	{
		dis[i]=edge[u][i];
		vis[i]=0;
	}
	vis[u]=1; dis[u]=0;
	for(i=1;i<=n;i++)
	{
		int min=1e10;u=-1;
		for(j=0;j<=n;j++)
		{
			if(!vis[j]&&dis[j]<min) {min=dis[j]; u=j;}
		}
		if(u==-1) break;
		vis[u]=1;
		for(j=0;j<=n;j++)
		{
			if(!vis[j]&&dis[u]+edge[u][j]<dis[j])
				dis[j]=dis[u]+edge[u][j];
		}
	}
	printf("%.2lf\n",dis[v]);
}
int main()
{
	while(scanf("%d",&n),n!=-1)
	{
		int i,j,k;
		double x,y1,y2;
		door[0].d[0].st[0]=TPoint(0,5); door[0].d[0].st[1]=TPoint(0,5);
		door[0].d[1].st[0]=TPoint(0,5); door[0].d[1].st[1]=TPoint(0,5);
		for(i=1;i<=n;i++)
		{
			scanf("%lf%lf%lf",&x,&y1,&y2);
			door[i].d[0].st[0]=TPoint(x,y1); door[i].d[0].st[1]=TPoint(x,y2);
			scanf("%lf%lf",&y1,&y2);
			door[i].d[1].st[0]=TPoint(x,y1); door[i].d[1].st[1]=TPoint(x,y2);
		}
		door[n+1].d[0].st[0]=TPoint(10,5); door[n+1].d[0].st[1]=TPoint(10,5);
		door[n+1].d[1].st[0]=TPoint(10,5); door[n+1].d[1].st[1]=TPoint(10,5);
		for(i=0;i<=4*n+4;i++) for(j=0;j<=4*n+4;j++) edge[i][j]=1e10;
		getedge();
		dijkstra(0,4*n+1);
	}
	return 0;
}


發佈了44 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章