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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值