做法:额,和FZU一题求最短路的某一题很像啊,把门两侧、起点、终点都化作图中的点。然后根据图中情况求出每个点的通达情况。
#include<cstdio> #include<cmath> #define eps 1e8 const int LMT=102; int wn,n; double gra[LMT][LMT]; struct wall { double y1,y2,x; }w[LMT]; struct point { double x,y; }p[LMT]; inline double max(double a,double b) { return a>b?a:b; } inline double min(double a,double b) { return a<b?a:b; } inline double length(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline int min(int a,int b) { return a<b?a:b; } void init(void) { int i,j; for(i=0;i<LMT;i++) for(j=0;j<LMT;j++) gra[i][j]=eps; wn=0;n=0; } bool can(point a,point b) { int i; if(a.x==b.x) { for(i=0;i<wn&&w[i].x!=a.x;i++); for(;i<wn&&w[i].x==a.x;i++) if(a.y<=w[i].y1&&w[i].y2<=b.y)return 0; return 1; } double k=(b.y-a.y)/(b.x-a.x); for( i=0;i<wn&&w[i].x<=a.x;i++); for(;i<wn&&w[i].x<b.x;i++) if(b.y-k*(b.x-w[i].x)<=w[i].y2&&b.y-k*(b.x-w[i].x)>=w[i].y1)return 0; return 1; } int main() { int doors,i,j,k; double x,y1,y2,y3,y4; while(~scanf("%d",&doors)&&doors!=-1) { init(); p[n].x=0;p[n].y=5;n++; for( i=0;i<doors;i++) { scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4); p[n].x=x;p[n].y=y1;n++;p[n].x=x;p[n].y=y2;n++; p[n].x=x;p[n].y=y3;n++;p[n].x=x;p[n].y=y4;n++; w[wn].x=x;w[wn].y1=0;w[wn].y2=y1;wn++; w[wn].x=x;w[wn].y1=y2;w[wn].y2=y3;wn++; w[wn].x=x;w[wn].y1=y4;w[wn].y2=10;wn++; } p[n].x=10;p[n].y=5;n++; for(i=0;i<n;i++) { for( j=i+1;j<n;j++) if(can(p[i],p[j])) gra[i][j]=gra[j][i]=length(p[i],p[j]); gra[i][i]=0; } for(k=0;k<n;k++) for( i=0;i<n;i++) if(gra[i][k]!=eps) for(j=0;j<n;j++) if(gra[k][j]!=eps) gra[i][j]=min(gra[i][j],gra[i][k]+gra[k][j]); printf("%.2lf\n",gra[0][n-1]); } return 0; }