POJ - 1039 Pipe

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lidengdengter/article/details/82188106

题目链接

题目给出管道上半部分各个拐点处的坐标(x,y),管道宽度为1,对应下半部分各个拐点处的坐标是(x,y-1),求直线穿过水管相交处的横坐标的最大值。

直线与每个拐点上下连线的线段若有交点则表示穿过管道,如果不能穿过,在第k节管道处无法穿过,则需要计算最大坐标x,即分别计算与第k-1节管子的上、下管壁相交, 求得最大坐标。

#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
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 sx,double sy):x(sx),y(sy){}
	point operator -(const point &w)const{  //相减 
		return point(x-w.x,y-w.y);
	}
	double operator ^(const point &w)const{ //叉积 
		return x*w.y-y*w.x;
	}
	double operator *(const point &w)const{ //点积 
		return x*w.x+y*w.y;
	}
}p[100];

struct line{
	point st,ed;
	line(){}
	line(point sa,point sb):st(sa),ed(sb){}
	pair<int,point>operator &(const line &w)const{ //两直线关系 
		point res=st;
		if(sgn((st-ed)^(w.st-w.ed))==0){
			if(sgn((st-w.ed)^(w.st-w.ed))==0)
				return make_pair(0,res); //重合
			else	
				return make_pair(1,res); //平行 
		}
		double tmp=((st-w.st)^(w.st-w.ed))/((st-ed)^(w.st-w.ed));
		res.x+=(ed.x-st.x)*tmp;
		res.y+=(ed.y-st.y)*tmp;
		return make_pair(2,res); //相交 
	}
}l[100],g[100]; 

bool isCross(line a,line b){  //直线和直线是否相交
	return
	sgn((b.st-a.ed)^(a.st-a.ed))*sgn((b.ed-a.ed)^(a.st-a.ed))<=0;
} 

int main(){
	int n;
	while(~scanf("%d",&n),n){
		int pnt=0;
		int lnt=0,gnt=0;
		for(int i=0;i<n;i++){
			scanf("%lf%lf",&p[pnt].x,&p[pnt].y);
			p[pnt+1].x=p[pnt].x;
			p[pnt+1].y=p[pnt].y-1.0;
			if(pnt!=0){
				l[lnt++]=line(p[pnt-2],p[pnt]);
				l[lnt++]=line(p[pnt-1],p[pnt+1]);
			}
			g[gnt++]=line(p[pnt],p[pnt+1]);
			pnt+=2;
		}
		bool flag=false;
		double ans=p[0].x;
		for(int i=0;i<pnt&&!flag;i++)
			for(int j=i+1;j<pnt;j++){
				if(i%2==0&&j==i+1)
					continue;
				line mp=line(p[i],p[j]);
				int k;
				for(k=0;k<gnt;k++)
					if(!isCross(mp,g[k])){
						if(k!=0){
							ans=max(ans,(mp&l[2*(k-1)]).second.x);
							ans=max(ans,(mp&l[2*(k-1)+1]).second.x);
						}
						break;
					}
				if(k==gnt){
					flag=true;
					break;
				}		
			}
		if(flag)
			printf("Through all the pipe.\n");
		else printf("%.2f\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/lidengdengter/article/details/82188106