HLG 1450 Farmer John【线段相交判断+最短路】
题意: 给一个起点和一个终点,然后给出 N 个互不相交的栅栏,问从起点到终点如果不穿过栅栏(可以接触)最少需要走多
远的距离。
分析: 如果两个点所在线段,没有其它线段与之相交,则可以在两点之间连一条线段,最后只要求出起点到终点的最短距离即可,
时间复杂度O(N^3)
CODE :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> #include<math.h> double min(double a,double b){ return a<b?a:b; } double max(double a,double b){ return a>b?a:b; } const double eps=1e-10; const double INF=9999999.0; double g[205][205]; struct node { double x,y; }a[202],b[202]; double dis(node a,node b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int inter(node a,node b,node c,node d) // 线段相交判断。。。 { if(min(a.x,b.x)>max(c.x,d.x)|| min(a.y,b.y)>max(c.y,d.y)|| min(c.x,d.x)>max(a.x,b.x)|| min(c.y,d.y)>max(a.y,b.y)) return 0; double h,i,j,k; h=(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); i=(b.x-a.x)*(d.y-a.y)-(b.y-a.y)*(d.x-a.x); j=(d.x-c.x)*(a.y-c.y)-(d.y-c.y)*(a.x-c.x); k=(d.x-c.x)*(b.y-c.y)-(d.y-c.y)*(b.x-c.x); return h*i<=eps&&j*k<=eps; } int n; double dijkstra() { int s[210]; double dis[210]; int i,j; memset(s,0,sizeof(s)); for(i=0;i<=2*(n+1);i++) dis[i]=INF; for(i=0;i<=2*(n+1);i++) dis[i]=g[1][i]; s[1]=1; int u,tmp; for(i=2;i<=2*(n+1);i++) { tmp=INF; u=1; for(j=1;j<=2*(n+1);j++) if((!s[j])&&dis[j]<tmp) { u=j; tmp=dis[j]; } s[u]=1; for(j=1;j<=2*(n+1);j++) if((!s[j])&&g[u][j]<INF&&g[u][j]+dis[u]<dis[j]) dis[j]=g[u][j]+dis[u]; } return dis[n+1+1]; } int main() { //freopen("D:data.in","r",stdin); //freopen("D:ce.txt","r",stdin); int i,j,k,t,flag; scanf("%d",&t); while(t--) { scanf("%lf%lf%lf%lf",&a[1].x,&a[1].y,&b[1].x,&b[1].y); scanf("%d",&n); if(n==0) { printf("%.6lf\n",dis(a[1],b[1])); continue; } for(i=2;i<=n+1;i++) scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y); for(i=0;i<=2*(n+1);i++) for(j=0;j<=2*(n+1);j++) g[i][j]=INF; for(i=1;i<=n+1;i++) // 建图。。。 { for(j=i+1;j<=n+1;j++) { flag=0; for(k=2;k<=n+1;k++) { if(k==i||k==j) continue; if(inter(a[i],a[j],a[k],b[k])) { flag=1; break; } } if(!flag) g[i][j]=g[j][i]=dis(a[i],a[j]); } for(j=i;j<=n+1;j++) { flag=0; if(i==j&&i!=1) continue; for(k=2;k<=n+1;k++) { if(k==i||k==j) continue; if(inter(a[i],b[j],a[k],b[k])) { flag=1; break; } } if(!flag) g[i][j+n+1]=g[j+n+1][i]=dis(a[i],b[j]); } for(j=i+1;j<=n+1;j++) { flag=0; for(k=2;k<=n+1;k++) { if(k==i||k==j) continue; if(inter(b[i],a[j],a[k],b[k])) { flag=1; break; } } if(!flag) g[i+n+1][j]=g[j][i+n+1]=dis(b[i],a[j]); } for(j=i+1;j<=n+1;j++) { flag=0; for(k=2;k<=n+1;k++) { if(k==i||k==j) continue; if(inter(b[i],b[j],a[k],b[k])) { flag=1; break; } } if(!flag) g[i+n+1][j+n+1]=g[j+n+1][i+n+1]=dis(b[i],b[j]); } } printf("%.6lf\n",dijkstra()); } return 0; }