The Doors ZOJ 1721(计算几何+线段相交+最短路)

The DoorsZOJ - 1721

You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length.



Input

The input data for the illustrated chamber would appear as follows.

2
4 2 7 8 9
7 3 4.5 6 7

The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.


Output

The output file should contain one line of output for each chamber. The line should contain the minimal path length rounded to two decimal places past the decimal point, and always showing the two decimal places past the decimal point. The line should contain no blanks.


Sample Input

1
5 4 6 7 8
2
4 2 7 8 9
7 3 4.5 6 7
-1


Sample Output

10.00
10.06

分析:
每一道墙会加入四个点,三条边,其实就是每加入一组点和一组边,就判断所有可以相连的点(实际上就是判断线段是否相交,不存在相交的线段组合的话就通过),把所有通过判断的线段存起来,最后来一个最短路就OK了
本来是POJ的题目,但是POJ这两天炸了。。。这能找ZOJ了

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<iomanip>
using namespace std;
const double eps=1e-8;
struct Vector{
	double x,y;
	Vector(){}
	Vector(double x,double y):x(x),y(y){}
};
typedef Vector point;
Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
Vector operator * (Vector a,Vector b){return Vector(a.x*b.x,a.y*b.y);}
Vector operator / (Vector a,Vector b){return Vector(a.x/b.x,a.y/b.y);}
double dot(Vector a,Vector b){
	return a.x*b.x+a.y*b.y;
}
double cross(Vector a,Vector b){
	return a.x*b.y-a.y*b.x;
}
struct line{
	point p1,p2;
	line(){}
	line(point p1,point p2):p1(p1),p2(p2){} 
};
double G[100][100];
vector<line> lv;
vector<point> pv;
bool is_inter(point pa1,point pa2,point pb1,point pb2){
	if(max(pa1.x,pa2.x)<=min(pb1.x,pb2.x)
	||max(pb1.x,pb2.x)<=min(pa1.x,pa2.x)
	||max(pa1.y,pa2.y)<=min(pb1.y,pb2.y)
	||max(pb1.y,pb2.y)<=min(pa1.y,pa2.y))return false;
	if(cross(pa2-pa1,pb1-pa1)*cross(pa2-pa1,pb2-pa1)<=0
	&&cross(pb2-pb1,pa1-pb1)*cross(pb2-pb1,pa2-pb1)<=0)return true;
	else return false;
}
double len(Vector a){
	return sqrt(dot(a,a));
}
vector<int> u,v;
vector<double> w;
double dis[100];
int main(){
	int n;
	cin>>n;
	while(n!=-1){
		for(int i=0;i<n*4+2+10;i++){
			dis[i]=10000;
		}
		u.clear();v.clear();w.clear();
		pv.clear();lv.clear();
		pv.push_back(point(0,5));
		double X,Y1,Y2,Y3,Y4;
		for(int i=0;i<n;i++){
			cin>>X>>Y1>>Y2>>Y3>>Y4;
			point p1(X,Y1),p2(X,Y2),p3(X,Y3),p4(X,Y4);
			point p[4]={p1,p2,p3,p4};
			pv.push_back(p1);pv.push_back(p2);pv.push_back(p3);pv.push_back(p4);
			point pu(X,10),pd(X,0);
			lv.push_back(line(pd,p1));lv.push_back(line(p2,p3));lv.push_back(line(p4,pu));
			for(int j=0;j<4;j++){
				for(int k=0;k<pv.size()-4;k++){
					point pa=p[j],pb=pv[k];
					int ok=1;
					for(int l=0;l<lv.size()-3;l++){
						if(is_inter(pa,pb,lv[l].p1,lv[l].p2))ok=0;
					}
					if(ok){
						u.push_back(k);
						v.push_back(i*4+1+j);
						w.push_back(len(pa-pb));
					}
				}
			}
		}
		/*for(int i=0;i<pv.size();i++){
			cout<<i<<' '<<pv[i].x<<' '<<pv[i].y<<endl;
		}*/
		for(int k=0;k<pv.size();k++){
			point pa(10,5),pb=pv[k];
			int ok=1;
			for(int l=0;l<lv.size();l++){
				if(is_inter(pa,pb,lv[l].p1,lv[l].p2))ok=0;
			}
			if(ok){
				u.push_back(k);
				v.push_back(n*4+1);
				w.push_back(len(pa-pb));
			}
		}
		dis[0]=0;
		//BF算法 
		/*for(int i=0;i<u.size();i++){
			cout<<i<<' '<<u[i]<<' '<<v[i]<<' '<<w[i]<<endl;
		}*/
		for(int i=0;i<n*4+2;i++){
			int is_renew=0;
			for(int j=0;j<u.size();j++){
				if(dis[v[j]]>dis[u[j]]+w[j]){
					dis[v[j]]=dis[u[j]]+w[j];
					is_renew=1;
				}
			}
			if(is_renew==0)break;
		}
		cout<<fixed<<setprecision(2)<<dis[n*4+1]<<endl;
		cin>>n;	
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41333528/article/details/80562551
ZOJ