题目链接:点击查看
题目大意:给出一个房间,房间内有许多墙壁(最多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;
}