POJ - 1556 The Doors(线段相交+最短路)

题目链接:点击查看

题目大意:给出一个房间,房间内有许多墙壁(最多18堵墙),现在要从(0,5)点到(10,5)点,问最短路程是多少

题目分析:若要使路程最短,肯定要在两点之间前进,这样我们可以在建好墙后,根据线段相交问题渐变,判断两个点之间是否有线段挡着,如果没有挡着,直接建边,边权为两点的直线距离,如果被挡着了,也就是存在一条线段和当前线段规范相交,则说明两点无法直接到达,则边权置为无穷大,建好边后直接跑最短路就是答案了,因为数值较小,用Floyd比较简单

代码:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;

const int N=110;

const double eps = 1e-8;

int sgn(double x){
	if(fabs(x) < eps)return 0;
	if(x < 0)return -1;
	else return 1;
}

struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){
		x = _x;
		y = _y;
	}
	void input(){
		scanf("%lf%lf",&x,&y);
	}
	Point operator -(const Point &b)const{
		return Point(x-b.x,y-b.y);
	}
	//叉积
	double operator ^(const Point &b)const{
		return x*b.y - y*b.x;
	}
	//点积
	double operator *(const Point &b)const{
		return x*b.x + y*b.y;
	}
	//返回两点的距离
	double distance(Point p){
		return hypot(x-p.x,y-p.y);
	}
};

struct Line{
	Point s,e;
	Line(){}
	Line(Point _s,Point _e){
		s = _s;
		e = _e;
	}
	//`两线段相交判断`
	//`2 规范相交`
	//`1 非规范相交`
	//`0 不相交`
	int segcrossseg(Line v){
		int d1 = sgn((e-s)^(v.s-s));
		int d2 = sgn((e-s)^(v.e-s));
		int d3 = sgn((v.e-v.s)^(s-v.s));
		int d4 = sgn((v.e-v.s)^(e-v.s));
		if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;
		return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
			(d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
			(d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
			(d4==0 && sgn((e-v.s)*(e-v.e))<=0);
	}
};

vector<Line>line;

vector<Point>point;

double maze[N][N];

bool check(Line l)
{
	if(sgn(l.s.distance(l.e))==0)
		return true;
	for(int i=0;i<line.size();i++)
	{
		if(line[i].segcrossseg(l)==2)
			return false;
	}
	return true;
}

void init()
{
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			maze[i][j]=1e10;
	line.clear();
	point.clear();
	point.push_back(Point(0,5));
	point.push_back(Point(10,5));
}

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	int n;
	while(scanf("%d",&n)!=EOF&&n!=-1)
	{
		init();
		for(int i=1;i<=n;i++)
		{
			double x,y[4];
			scanf("%lf",&x);
			for(int j=0;j<4;j++)
			{
				scanf("%lf",y+j);
				point.push_back(Point(x,y[j]));
			}
			line.push_back(Line(Point(x,0),Point(x,y[0])));
			line.push_back(Line(Point(x,y[1]),Point(x,y[2])));
			line.push_back(Line(Point(x,y[3]),Point(x,10)));
		}
		for(int i=0;i<point.size();i++)
			for(int j=i;j<point.size();j++)
			{
				if(check(Line(point[i],point[j])))
					maze[i][j]=maze[j][i]=point[i].distance(point[j]);
				else
					maze[i][j]=1e10;
			}
		for(int k=0;k<point.size();k++)
			for(int i=0;i<point.size();i++)
				for(int j=0;j<point.size();j++)
					maze[i][j]=min(maze[i][j],maze[i][k]+maze[k][j]);
		printf("%.2f\n",maze[0][1]);
	}
	
	
 
 
 
 
 
 
 
	
	
	
	
	
	
	
	
	
	return 0;
}
发布了577 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104093746