计算几何+最短路
通过线段是否完全相交判断两点的连通性。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const double inf=1e10;
const double EP=1e-8;
struct Point{
double x, y;
}p[105]; //4*n+2
struct Segline{
Point s, e;
}seg[65]; //3*n
int n, vis[105];
double a[105][105], d[105];
double dist(Point p1, Point p2){
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double x_mult(Point sp, Point ep, Point op){
return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
}
bool intersect(Segline l1, Segline l2){
if((x_mult(l1.s,l2.e,l2.s)*x_mult(l1.e,l2.e,l2.s)<-EP)&&
(x_mult(l2.s,l1.e,l1.s)*x_mult(l2.e,l1.e,l1.s)<-EP))
return true;
return false;
}
void init(){
p[0].x=0;p[0].y=5;
p[4*n+1].x=10;p[4*n+1].y=5;
Point p1, p2;
int i, j, k;
for(i=0; i<n; i++){
scanf("%lf%lf%lf%lf%lf", &p[i*4+1].x, &p[i*4+1].y, &p[i*4+2].y, &p[i*4+3].y, &p[i*4+4].y);
p1.x=p2.x=p[i*4+2].x=p[i*4+3].x=p[i*4+4].x=p[i*4+1].x;
p1.y=0;p2.y=10;
seg[i*3].s=p1;seg[i*3].e=p[i*4+1];
seg[i*3+1].s=p[i*4+2];seg[i*3+1].e=p[i*4+3];
seg[i*3+2].s=p[i*4+4];seg[i*3+2].e=p2;
}
Segline st;
for(i=0; i<4*n+2; i++)
for(j=i+1; j<4*n+2; j++){
a[i][j]=a[j][i]=dist(p[i], p[j]);
for(k=(i+3)/4*3; k<(j-1)/4*3; k++){
st.s=p[i];st.e=p[j];
if(intersect(st, seg[k])){
a[i][j]=a[j][i]=inf;
break;
}
}
}
}
void dijkstra(int st){
int i, j, flag;
double tmp;
for(i=0; i<4*n+2; i++){
d[i]=a[st][i];
}
memset(vis, 0, sizeof(vis));
vis[st]=1;
for(i=0; i<4*n+1; i++){
tmp=inf;
for(j=0; j<4*n+2; j++){
if(!vis[j]&&d[j]<tmp){
tmp=d[j];
flag=j;
}
}
vis[flag]=1;
for(j=0; j<4*n+2; j++){
if(!vis[j]&&d[j]>d[flag]+a[flag][j])
d[j]=d[flag]+a[flag][j];
}
}
}
void solve(){
dijkstra(0);
printf("%.2f\n", d[4*n+1]);
}
int main(){
//freopen("1.txt", "r", stdin);
int T;
while(scanf("%d", &n)&&n!=-1){
init();
solve();
}
return 0;
}