POJ 2074 Line of Sight 计算几何
题意:
给出房子,障碍物,观光线(都为平行于x轴的线段)。问在观光线上能看到整个房子的最长距离
分析:
将房屋的端点与障碍物的端点连线,求出与观光线的横坐标。这些坐标会把观光线分成多个区间,然后枚举每一个区间的中点,来判断这个区间是否能看到整个房子
要注意的是:不一定每个障碍物都在房屋与观光线之间,与房屋或观光线在同一条直线的可以忽略掉
如果你用的G++,double输出格式为%f
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define eps 1e-8 #define INF 1e9 #define OK sgn(tmp-lx1)>0 && sgn(tmp-lx2<0) using namespace std; typedef struct Point { double x,y; Point() {}; Point(double xx,double yy) { x=xx; y=yy; } } Vector; struct Line { Point p,q; Line() {}; Line(Point pp,Point qq) { p=pp; q=qq; } }; int sgn(double x) { if(fabs(x)<eps) return 0; return x<0? -1:1; } double crs_prdct(Vector a,Vector b) { return a.x*b.y-b.x*a.y; } Vector operator - (Point a,Point b) { return Vector(a.x-b.x,a.y-b.y); } double calcu(Point a,Point b,double y) { return (a.x-b.x)/(a.y-b.y)*(y-a.y)+a.x; } const int maxn=105; Line hou,pro,obs[maxn]; double dot[maxn]; int main() { // freopen("in.txt","r",stdin); int n,m; double x1,x2,y,lx1,lx2,ly; while(scanf("%lf%lf%lf",&x1,&x2,&y)) { if(x1==0 && x2==0 && y==0) break; hou=Line(Point(x1,y),Point(x2,y)); scanf("%lf%lf%lf",&lx1,&lx2,&ly); scanf("%d",&n); m=0; for(int i=0; i<n; i++) { scanf("%lf%lf%lf",&x1,&x2,&y); if(sgn(y-hou.p.y)>=0 || sgn(y-ly)<=0) continue; obs[m++]=Line(Point(x1,y),Point(x2,y)); } int cnt=0; dot[cnt++]=lx1; double tmp; for(int i=0; i<m; i++) { if(obs[i].p.y>=hou.p.y || obs[i].p.y<ly) continue; tmp=calcu(hou.p,obs[i].p,ly); if(OK) dot[cnt++]=tmp; tmp=calcu(hou.p,obs[i].q,ly); if(OK) dot[cnt++]=tmp; tmp=calcu(hou.q,obs[i].p,ly); if(OK) dot[cnt++]=tmp; tmp=calcu(hou.q,obs[i].q,ly); if(OK) dot[cnt++]=tmp; } dot[cnt++]=lx2; sort(dot,dot+cnt); double ans=0; tmp=0; for(int i=0; i<cnt-1; i++) { bool flag=true; Point mid=Point((dot[i]+dot[i+1])/2,ly); for(int j=0; j<m; j++) { if(sgn(crs_prdct(hou.p-mid,obs[j].q-mid))<=0 && sgn(crs_prdct(hou.q-mid,obs[j].p-mid))>=0) { flag=false; break; } } if(flag) { tmp+=dot[i+1]-dot[i]; ans=max(ans,tmp); } else tmp=0; } if(sgn(ans)>0) printf("%.2f\n",ans); else puts("No View"); } return 0; }