ZOJ 1721 The Doors dijstra+计算几何

做法:额,和FZU一题求最短路的某一题很像啊,把门两侧、起点、终点都化作图中的点。然后根据图中情况求出每个点的通达情况。

#include<cstdio>
#include<cmath>
#define eps 1e8
const int LMT=102;
int wn,n;
double gra[LMT][LMT];
struct wall
{
	double y1,y2,x;
}w[LMT];
struct point
{
	double x,y;
}p[LMT];
inline double max(double a,double b)
{
	return a>b?a:b;
}
inline double min(double a,double b)
{
	return a<b?a:b;
}
inline double length(point a,point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline int min(int a,int b)
{
	return a<b?a:b;
}
void init(void)
{
	int i,j;
	for(i=0;i<LMT;i++)
		for(j=0;j<LMT;j++)
			gra[i][j]=eps;
		wn=0;n=0;
}
bool can(point a,point b)
{
	int i;
	if(a.x==b.x)
	{
		for(i=0;i<wn&&w[i].x!=a.x;i++);
		for(;i<wn&&w[i].x==a.x;i++)
			if(a.y<=w[i].y1&&w[i].y2<=b.y)return 0;
		return 1;
	}
	double k=(b.y-a.y)/(b.x-a.x);
	for( i=0;i<wn&&w[i].x<=a.x;i++);
	for(;i<wn&&w[i].x<b.x;i++)
		if(b.y-k*(b.x-w[i].x)<=w[i].y2&&b.y-k*(b.x-w[i].x)>=w[i].y1)return 0;
	return 1;
}
int main()
{
	int doors,i,j,k;
	double x,y1,y2,y3,y4;
	while(~scanf("%d",&doors)&&doors!=-1)
	{
		init();
		p[n].x=0;p[n].y=5;n++;
		for( i=0;i<doors;i++)
		{
			scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
			p[n].x=x;p[n].y=y1;n++;p[n].x=x;p[n].y=y2;n++;
			p[n].x=x;p[n].y=y3;n++;p[n].x=x;p[n].y=y4;n++;
			w[wn].x=x;w[wn].y1=0;w[wn].y2=y1;wn++;
			w[wn].x=x;w[wn].y1=y2;w[wn].y2=y3;wn++;
			w[wn].x=x;w[wn].y1=y4;w[wn].y2=10;wn++;
		}
		p[n].x=10;p[n].y=5;n++;
		for(i=0;i<n;i++)
		{
			for( j=i+1;j<n;j++)
				if(can(p[i],p[j]))
					gra[i][j]=gra[j][i]=length(p[i],p[j]);
				gra[i][i]=0;
		}
        for(k=0;k<n;k++)
			for( i=0;i<n;i++)
				if(gra[i][k]!=eps)
				for(j=0;j<n;j++)
					if(gra[k][j]!=eps)
					   gra[i][j]=min(gra[i][j],gra[i][k]+gra[k][j]);
				printf("%.2lf\n",gra[0][n-1]);
	}
	return 0;
}


你可能感兴趣的:(ZOJ 1721 The Doors dijstra+计算几何)