POJ 1556 The Doors 点与线段交+最短路

    xiaoxiao2025-07-27  3

    题目链接:http://poj.org/problem?id=1556

    题目大意:一个房间里有很多墙,每道墙上有两个门,求从房间左边中点到右边中点的最短距离。如图:

     

    这道题目说起来就是一道最短路的题,但是两点之间是否能够走,需要判断一下两点之间的连线是不是跟墙有交点,就是计算几何的判断线段相交问题。两类典型的题合在一起了。

    由于数据范围小的可怜,无脑暴力+floyd都能够过= =

     

    AC代码:

    #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #define MAXN 50 #define INF 1000000 using namespace std; struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y){} }; typedef Point Vector; Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);} Vector operator - (Point A,Point B) {return Vector(A.x-B.x,A.y-B.y);} Vector operator * (Vector A,double p) {return Vector(A.x*p,A.y*p);} double Dot(Vector A,Vector B) {return A.x*B.x + A.y*B.y ;} double Length(Vector A) {return sqrt(Dot(A,A));} double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} struct Line { Point P; Vector v; }; double GetLineIntersection(Line A,Line B) //返回交点相对P的t值 { Point P=A.P,Q=B.P; Vector v=A.v,w=B.v; Vector u=P-Q; double t=Cross(w,u) / Cross(v,w); return t; } //以上是计算几何基本内容 int n; Point points[4*MAXN];//记录点 double dis[4*MAXN][4*MAXN];//记录距离 Line lines[MAXN][3];//记录线段 int main() { Line l; Vector v,w; Point a,b; double x,t,t2; int i,j,k,o,mark; while(cin>>n) { if(n==-1) break; //初始化起点终点 points[n*4].x=0; points[n*4+1].x=10; points[n*4].y=points[n*4+1].y=5; for(i=0;i<n;i++) { cin>>x>>points[i*4+0].y>>points[i*4+1].y>>points[i*4+2].y>>points[i*4+3].y; a.x=b.x=points[i*4+0].x=points[i*4+1].x=points[i*4+2].x=points[i*4+3].x=x; a.y=0;b.y=10; //每道墙3条线 a-0 1-2 3-b lines[i][0].P=a; lines[i][0].v=points[i*4+0]-a; lines[i][1].P=points[i*4+1]; lines[i][1].v=points[i*4+2]-points[i*4+1]; lines[i][2].P=points[i*4+3]; lines[i][2].v=b-points[i*4+3]; } //设置距离初始值 for(i=0;i<4*n+2;i++) for(j=0;j<=i;j++) dis[i][j]=dis[j][i]=INF; //枚举两两点对 for(i=0;i<4*n+2;i++) for(j=0;j<i;j++) { if(points[i].x==points[j].x) continue; v=points[i]-points[j]; //给两点之间连线段赋值 l.P=points[j]; l.v=v; mark=0;//标记 //枚举所有的线段 for(k=0;k<n;k++) for(o=0;o<3;o++) { if(mark) break; t=GetLineIntersection(l,lines[k][o]); t2=GetLineIntersection(lines[k][o],l); if(t>0&&t<1&&t2>0&&t2<1)//如果交点在线段上,不能连 { mark=1; break; } } if(mark==0) dis[i][j]=dis[j][i]=Length(l.v);//可以连,更新距离 } //floyd跑最短路 for(k=0;k<4*n+2;k++) for(i=0;i<4*n+2;i++) for(j=0;j<4*n+2;j++) dis[i][j]=dis[i][j]<dis[i][k]+dis[k][j]?dis[i][j]:dis[i][k]+dis[k][j]; printf("%0.2f\n",dis[n*4+1][n*4+0]); } }

    转载请注明原文地址: https://ju.6miu.com/read-1301123.html
    最新回复(0)