题意:给你一个10*10的正方形的盒子,里面有一些线段,让你求从坐标(0,5)出发到坐标(10,5)的最短路径。
思路:判断任意两条线段的端点连线与其它线段是否有交点即可。最后用一个最短路径模板就可以了。
补充两知识点:
① 快速排斥实验:如果两条边所在矩形不相交则一定不相交,即满足
设线段a为(x1,y1)--(x2,y2) 线段b为(x3,y3)--(x4,y4)
这是判断可能相交的条件:min(x1,x2)<=max(x3,x4) && min(x3,x4)<=max(x1,x2) && min(y1,y2)<=max(y3,y4) && min(y3,y4)<=max(y1,y2) 才可能相交。
②跨立实验:此链接有详解:https://blog.csdn.net/HXX904/article/details/116273561?spm=1001.2014.3001.5501
最后用Dijstra跑一遍最短路就OK啦。
AC代码:
#include<stdio.h> #include<string.h> #include<string> #include<math.h> #include<iostream> #include<algorithm> using namespace std; #define eps 1e-8 typedef long long ll; const int N=100; const double inf=1e8; int n; double s[N][N],book[N]; double dis[N]; struct node { double x,y; } p[N]; int pan(double a,double b,double c,double d,double a1,double b1,double c1,double d1) { if(!(min(a,c)<=max(a1,c1)&&min(a1,c1)<=max(a,c)&&min(b,d)<=max(b1,d1)&&min(b1,d1)<=max(b,d)))//快速排斥实验 return 0; double u=((c-a)*(d1-b)-(d-b)*(c1-a))*((c-a)*(b1-b)-(d-b)*(a1-a)); double v=((c1-a1)*(b-b1)-(d1-b1)*(a-a1))*((c1-a1)*(d-b1)-(d1-b1)*(c-a1)); if(u>=0.0||v>=0.00)//跨立实验 利用叉乘判断 return 0; return 1; } double solve(double a,double b,double c,double d)//判断是否能直接到达,可以的话,计算距离 { double a1,b1,c1,d1; for(int i=0; i<n; i++) { a1=c1=p[4*i+1].x; b1=0,d1=p[4*i+1].y; if(pan(a,b,c,d,a1,b1,c1,d1))return inf; b1=p[4*i+2].y,d1=p[4*i+3].y; if(pan(a,b,c,d,a1,b1,c1,d1))return inf; b1=p[4*i+4].y,d1=10; if(pan(a,b,c,d,a1,b1,c1,d1))return inf; } return sqrt((c-a)*(c-a)+(d-b)*(d-b)); } void dijstra() { memset(book,0,sizeof(book)); for(int i=0; i<=99; i++)dis[i]=s[0][i]; dis[0]=0; for(int i=0; i<=4*n+1; i++) { double minn=inf; int k; for(int j=0; j<=4*n+1; j++) if(!book[j]&&dis[j]<minn) minn=dis[k=j]; book[k]=1; for(int j=0; j<=4*n+1; j++) if(dis[j]>dis[k]+s[k][j]) dis[j]=dis[k]+s[k][j]; } } int main() { while(scanf("%d",&n)&&n!=-1) { p[0].x=0,p[0].y=5; for(int i=0; i<n; i++) { double x,y1,y2,y3,y4; cin>>x>>y1>>y2>>y3>>y4; p[i*4+1].x=x,p[i*4+1].y=y1; p[i*4+2].x=x,p[i*4+2].y=y2; p[i*4+3].x=x,p[i*4+3].y=y3; p[i*4+4].x=x,p[i*4+4].y=y4; } p[n*4+1].x=10,p[n*4+1].y=5; for(int i=0; i<=4*n+1; i++) { s[i][i]=0.0; for(int j=i+1; j<=4*n+1; j++) s[i][j]=s[j][i]=solve(p[i].x,p[i].y,p[j].x,p[j].y); } dijstra(); printf("%.2f\n",dis[4*n+1]); } return 0; }