线段求交+spfa.
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #define maxn 1050 #define eps 1e-8 #define inf 0x3f3f3f3f using namespace std; struct point { double x,y; point(double x,double y):x(x),y(y) {} point() {} friend point operator -(point x,point y) { return point(x.x-y.x,x.y-y.y); } friend bool operator ==(point x,point y) { return ((x.x==y.x) && (x.y==y.y)); } }p[maxn*50]; struct line { point x,y,dt; line (point x,point y,point dt):x(x),y(y),dt(dt) {} line () {} friend double operator *(line x,line y) { return x.x.x*y.x.y-x.x.y*y.x.x; } friend bool operator ==(line x,line y) { return ((x.x==y.x) && (x.y==y.y)); } }l[maxn*50]; struct edge { int v,nxt; double w; }e[maxn*100]; int n,g[maxn*50],tot1=0,tot2=0,nume=1; double x,a,b,c,d,dis[maxn*50]; queue <int> q; bool vis[maxn*50]; double dist(point x,point y) {return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));} void addedge(int u,int v,double w) { e[++nume].v=v;e[nume].w=w; e[nume].nxt=g[u];g[u]=nume; } point ask_cross(line x,line y) { double a,b,c,d,e,f; a=x.x.y-x.y.y;b=x.y.x-x.x.x;c=x.x.x*x.y.y-x.x.y*x.y.x; d=y.x.y-y.y.y;e=y.y.x-y.x.x;f=y.x.x*y.y.y-y.x.y*y.y.x; return point((b*f-c*e)/(a*e-b*d),(a*f-c*d)/(b*d-a*e)); } bool isin(point x,line y) { point ret=x-y.x; if (!y.dt.x) { double mn=min(y.x.y,y.y.y),mx=max(y.x.y,y.y.y); return (x.y>mn && x.y<mx); } else return (ret.x/y.dt.x>0 && ret.x/y.dt.x<1); } bool check(point x,point y) { line now=line(x,y,y-x); for (int i=1;i<=tot2;i++) { if (fabs(now*l[i])<eps) continue; point cross=ask_cross(now,l[i]); if (isin(cross,l[i]) && isin(cross,now)) return false; } return true; } void spfa() { while (!q.empty()) q.pop();memset(vis,false,sizeof(vis)); for (int i=2;i<=tot1;i++) dis[i]=inf; dis[1]=0;vis[1]=true;q.push(1); while (!q.empty()) { int head=q.front();q.pop(); for (int i=g[head];i;i=e[i].nxt) { int v=e[i].v; if (dis[v]>dis[head]+e[i].w) { dis[v]=dis[head]+e[i].w; if (!vis[v]) {q.push(v);vis[v]=true;} } } vis[head]=false; } } int main() { for (;;) { memset(g,0,sizeof(g));nume=1;tot1=tot2=0; scanf("%d",&n);if (n==-1) break; p[++tot1]=point(0,5); for (int i=1;i<=n;i++) { scanf("%lf%lf%lf%lf%lf",&x,&a,&b,&c,&d); p[++tot1]=point(x,a);p[++tot1]=point(x,b);p[++tot1]=point(x,c);p[++tot1]=point(x,d); l[++tot2]=line(point(x,0),point(x,a),point(x,a)-point(x,0)); l[++tot2]=line(point(x,b),point(x,c),point(x,c)-point(x,b)); l[++tot2]=line(point(x,d),point(x,10),point(x,10)-point(x,d)); } p[++tot1]=point(10,5); for (int i=1;i<=tot1;i++) for (int j=i+1;j<=tot1;j++) { if (check(p[i],p[j])) { addedge(i,j,dist(p[i],p[j])); addedge(j,i,dist(p[i],p[j])); } } spfa(); printf("%.2f ",dis[tot1]); } return 0; }