线段判严格相交+最短路建图——poj1556
/* 两两枚举端点,如果线段不和任何一条线段相交,则连一条边,然后跑最短路 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; #define N 205 #define db double const db eps=1e-6; int sign(db k){if(k>eps)return 1;else if(k<-eps)return -1;return 0;} int cmp(db k1,db k2){return sign(k1-k2);} struct point{ db x,y; point(){} point(db _x,db _y):x(_x),y(_y){} point operator + (const point &k1) const {return point(x+k1.x,y+k1.y);} point operator - (const point &k1) const {return point(x-k1.x,y-k1.y);} db abs() {return sqrt(x*x+y*y);} db dis(point k1) {return (*this-k1).abs();} }; db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} int checkSS(point k1,point k2,point k3,point k4){//判严格相交 return sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<0 && sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<0; } struct line{ point p[2]; }; int n,totp,totl; point p[N]; line l[N]; int check(point k1,point k2){ if(k1.dis(k2)==0)return 1; for(int i=1;i<=totl;i++)//不能有边和其相交 if(checkSS(k1,k2,l[i].p[0],l[i].p[1]))return 0; return 1; } struct Edge{ int to,nxt;db w; }e[N*N*2]; int head[N],tot; db mp[N][N]; void init(){ memset(head,-1,sizeof head); tot=0; } void add(int u,int v,db w){ e[tot].to=v;e[tot].nxt=head[u];e[tot].w=w;head[u]=tot++; mp[u][v]=mp[v][u]=1; } db dis[N]; int vis[N]; priority_queue<pair<db,int> >pq; void dijkstra(){ memset(vis,0,sizeof vis); int s=0,t=totp; for(int i=0;i<=totp;i++)dis[i]=1e16; dis[s]=0;pq.push(make_pair(0,s)); while(pq.size()){ int now=pq.top().second;pq.pop(); if(vis[now])continue; vis[now]=1; for(int i=head[now];i!=-1;i=e[i].nxt){ int v=e[i].to; if(!vis[v] && dis[v]>dis[now]+e[i].w){ dis[v]=dis[now]+e[i].w; pq.push(make_pair(-dis[v],v)); } } } printf("%.2f\n",dis[t]); } int main(){ while(scanf("%d",&n) && n!=-1){ init();totp=totl=0; p[totp++]=point(0,5); for(int i=1;i<=n;i++){ db x;scanf("%lf",&x); point pp[6]; for(int i=0;i<6;i++)pp[i].x=x; pp[0].y=0;pp[5].y=10; for(int i=1;i<=4;i++)scanf("%lf",&pp[i].y); for(int i=0;i<6;i++)p[totp++]=pp[i]; for(int i=0;i<6;i+=2){ ++totl; l[totl].p[0]=pp[i]; l[totl].p[1]=pp[i+1]; } } p[totp]=point(10,5); /* for(int i=0;i<=totp;i++)cout<<p[i].x<<" "<<p[i].y<<'\n'; for(int i=1;i<=totl;i++){ point k1=l[i].p[0],k2=l[i].p[1]; cout<<k1.x<<" "<<k1.y<<' '; cout<<k2.x<<" "<<k2.y<<'\n'; } */ for(int i=0;i<=totp;i++) for(int j=i+1;j<=totp;j++){ if(check(p[i],p[j])){ add(i,j,p[i].dis(p[j])); add(j,i,p[i].dis(p[j])); } } dijkstra(); } }