梦,才是最真的现实

导航

poj 1556 计算几何+最短路

主要是构图花了不少时间,应该一小时能够搞定的,却花了三个小时,最大的原因是初始化没有做好

说下题目,我们给每个点一个编号,然后求出每两个点之间的最短路径,肯定是直线最短。

然后为了简化,我们可以只求这个点和他后面的点的关系(因为必然可以向前走,不可能折回来再往前走才是最短的),

注意一点,不是每两个点之间都能直达的,得判断其中经过的路径有没有被墙堵住了(判断直线和线段的关系 )

判断如下

bool check(int now,int no,int next,int h)//第几行第几个,要到第几行第几个
{
	int i,j;
	for(i=now+1;i<next;i++)
	{
		for(j=0;j<6;j+=2)
		{
			if(xmult(wall[now][no],wall[i][j],wall[next][h])*xmult(wall[now][no],wall[i][j+1],wall[next][h])<eps) //遇到障碍
			{
		//		printf("J:%d   k:%d    (%.2lf,%.2lf)     (%.2lf,%.2lf) \n",i,j,wall[i][j].x,wall[i][j].y,wall[i][j+1].x,wall[i][j+1].y);
				return false;
			}
		}
	}
	return true;
}

图构好之后,DIJ可解,附代码

#include<stdio.h>
#include<string.h>
#include<math.h>
#define eps 1e-8
#define val 100
#define INF 1<<25
#define zero(x) (((x)>0?(x):-(x))<eps)
typedef struct {double x,y;} point;
point wall[20][6];
double dis[val],map[val][val];
bool in[val];
int n,m,s,t,num;
void dij();
void create_link();
double xmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int main()
{
	int i,j;
	double x;
	while(scanf("%d",&num)&&num!=-1)
	{
		n=num*4+1;
		for(i=1;i<=num;i++)
		{
			scanf("%lf",&x);
			wall[i][0].y=0;
			wall[i][5].y=10;
			for(j=0;j<6;j++)
			{
				wall[i][j].x=x;
	//			printf("XX:%.2lf \n",x);
			}
			for(j=1;j<=4;j++)
				scanf("%lf",&wall[i][j].y);
		}
	//	printf("X:%.2lf\n",wall[1][1].x);
		for(j=0;j<6;j++)
		{
			wall[0][j].x=0;
			wall[0][j].y=5;
			wall[num+1][j].x=10;
			wall[num+1][j].y=5;
		}
		create_link();
		dij();
		printf("%.2lf\n",dis[t]);
	}
	return 0;
}
void create_link()
{
	int i,j,k,v;
	bool check(int ,int ,int ,int );
	double dist(point ,point);
	s=0,t=n;
	for(i=0;i<=n;i++)
		for(j=0;j<=n;j++)
			map[i][j]=INF;
/*	printf("(%.2lf,%.2lf)   (%.2lf,%.2lf)   dis:%.2lf\n",wall[0][1].x,wall[0][1].y,wall[2][2].x,wall[2][2].y,dist(wall[0][1],wall[2][2]));
	printf("(%.2lf,%.2lf)   (%.2lf,%.2lf)   dis:%.2lf\n",wall[2][2].x,wall[2][2].y,wall[3][1].x,wall[3][1].y,dist(wall[2][2],wall[3][1]));
    printf("CHECK:%d \n",check(0,0,2,2));*/
	for(i=0;i<=num;i++)
		for(j=1;j<=4;j++)
		{
			for(k=i+1;k<=num+1;k++)
			{
				for(v=1;v<=4;v++)
					if(check(i,j,k,v))
					{
				//		if((k-1)*4+v==n) printf("I:%d   j:%d   k:%d  v:%d\n",i,j,k,v);
			//			printf("I:%d   j:%d    k:%d    v:%d    dis:%.2lf \n",i,j,k,v,dist(wall[i][j],wall[k][v]));
						if(i==0)   
						{
							if(k==num+1) map[s][n]=dist(wall[i][j],wall[k][v]);
							else map[s][(k-1)*4+v]=dist(wall[i][j],wall[k][v]);
						}
						else if(k==num+1)
							map[(i-1)*4+j][n]=dist(wall[i][j],wall[k][v]);
						else 
							map[(i-1)*4+j][(k-1)*4+v]=dist(wall[i][j],wall[k][v]);
					}
						
			}
		}
/*	for(i=0;i<=n;i++)
	{
		for(j=0;j<=n;j++)
			if(map[i][j]==INF) printf("-1 ");
			else
				printf("%.2lf ",map[i][j]);
		putchar('\n');
	}*/
//	printf("check:%d\n", check(0,0,n,0));
}
bool check(int now,int no,int next,int h)
{
	int i,j;
	for(i=now+1;i<next;i++)
	{
		for(j=0;j<6;j+=2)
		{
			if(xmult(wall[now][no],wall[i][j],wall[next][h])*xmult(wall[now][no],wall[i][j+1],wall[next][h])<eps) //遇到障碍
			{
		//		printf("J:%d   k:%d    (%.2lf,%.2lf)     (%.2lf,%.2lf) \n",i,j,wall[i][j].x,wall[i][j].y,wall[i][j+1].x,wall[i][j+1].y);
				return false;
			}
		}
	}
	return true;
}
double dist(point p,point q)
{
	return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
void dij()
{
	int i,j,v;
	double min;
	memset(in,false,sizeof(in));
	for(i=0;i<=n;i++)
		dis[i]=map[s][i];
	dis[s]=0;
	in[s]=true;
	for(i=0;i<n;i++)
	{
		v=-1;
		min=INF;
		for(j=0;j<=n;j++)
			if(!in[j]&&dis[j]<min)
			{
				min=dis[j];
				v=j;
			}
		if(v==-1) return ;
		in[v]=true;
		for(j=0;j<=n;j++)
			if(!in[j]&&dis[j]>min+map[v][j])
				dis[j]=min+map[v][j];
	}
}


posted on 2012-08-14 18:46  梦,才是最真的现实  阅读(130)  评论(0编辑  收藏  举报