1051-最短路径
描述
在一些美国主要城市里,为企业传送文件和小物品的自行车快递长期以来就是流动运输服务的一部分。波士顿的骑车人是不同寻常的一族。他们以超速、不遵守单行道和红绿灯、无视汽车、出租、公交和行人的存在而臭名远扬。快递服务竞争激烈。比利快递服务公司(BBMs)也不例外。为发展业务,制定合理的收费,BBMS正根据快递员能走的最短路线制定一项快递收费标准。而你则要替BBMS编写一个程序来确定这些路线的长度。
以下假设可以帮助你简化工作:
●快递员可以在地面上除建筑物内部以外的任何地方骑车。
●地形不规则的建筑物可以认为是若干矩形的合并。并规定,任何相交矩形拥有共同内部,而且是同一建筑物的一部分。
●尽管两个不同的建筑物可能非常接近,但永远不会重叠。(快递员可以从任意两个建筑物之间穿过。他们能够绕过最急的拐弯,可以贴着建筑物的边缘疾驶。)
●起点和终点不会落在建筑物内部。
●总有一条连接起讫点的线路。
下图是一张典型的鸟瞰图。
输入
第一行:n
场景中描述建筑物的矩形个数。0<=n<=20
第二行:x1、y1、x2、y2,为路线起讫点的x 和y坐标。
余下n行:x1、y1、x2、y2、x3、y3,为矩形三个顶点的坐标,所有x 、y坐标是属于0到1000(包含0和1000)的实数,每行中相邻的坐标由一个或多个空格分开。
输出
输出应给出从起点到终点的最短线路的长度,精确到小数点后第二位。
样例输入
5
6.5 9 10 3
1 5 3 3 6 6
5.25 2 8 2 8 3.5
6 10 6 12 9 12
7 6 11 6 11 8
10 7 11 7 11 11
样例输出
7.28
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; #define INF 1000000000 #define EPS 1e-6 struct Point { double x,y; }p[100],s,t; struct Rectangle { Point p1,p2,p3,p4; }rec[25]; struct Vector { double x,y; }; int n; double path[100][100]; double dis[100]; bool zero(const double a) { return (fabs(a)<EPS); } double dot(Vector v1,Vector v2) { double x1,x2,y1,y2; x1=v1.x; y1=v1.y; x2=v2.x; y2=v2.y; return x1*x2+y1*y2; } double cross(Vector v1,Vector v2) { double x1,x2,y1,y2; x1=v1.x; y1=v1.y; x2=v2.x; y2=v2.y; return x1*y2-x2*y1; } void getRect(Rectangle &rec,Point p1,Point p2,Point p3,Point &p4) { Vector v1,v2,v3; v1.x=p2.x-p1.x; v1.y=p2.y-p1.y; v2.x=p3.x-p1.x; v2.y=p3.y-p1.y; v3.x=p3.x-p2.x; v3.y=p3.y-p2.y; if(zero(dot(v1,v2))) { p4.x=p3.x+v1.x; p4.y=p3.y+v1.y; rec.p1=p1; rec.p2=p2; rec.p3=p4; rec.p4=p3; } else if(zero(dot(v1,v3))) { p4.x=p1.x+v3.x; p4.y=p1.y+v3.y; rec.p1=p2; rec.p2=p3; rec.p3=p4; rec.p4=p1; } else { p4.x=p1.x-v3.x; p4.y=p1.y-v3.y; rec.p1=p3; rec.p2=p1; rec.p3=p4; rec.p4=p2; } } bool pointInsideRectangle(Point p,Rectangle rec) { Vector v1,v2,v3,v4; double c1,c2,c3,c4; v1.x=rec.p1.x-p.x;v1.y=rec.p1.y-p.y; v2.x=rec.p2.x-p.x;v2.y=rec.p2.y-p.y; v3.x=rec.p3.x-p.x;v3.y=rec.p3.y-p.y; v4.x=rec.p4.x-p.x;v4.y=rec.p4.y-p.y; c1=cross(v1,v2); c2=cross(v2,v3); c3=cross(v3,v4); c4=cross(v4,v1); if(c1*c2<EPS||c2*c3<EPS||c3*c4<EPS||c4*c1<EPS) return 0; return 1; } bool getIntersectPoint(Point &p0, Point p1, Point p2, Point p3, Point p4) { double k, k1; if (zero(p2.x-p1.x) && zero(p4.x-p3.x)) return 0; if (zero((p2.y-p1.y)/(p2.x-p1.x) - (p4.y-p3.y)/(p4.x-p3.x))) return 0; if (zero(p2.x-p1.x)) { k = (p4.y - p3.y) / (p4.x - p3.x); p0.x = p1.x; p0.y = k * (p0.x - p3.x) + p3.y; } else if (zero(p4.x-p3.x)) { k=(p2.y-p1.y)/(p2.x-p1.x); p0.x = p3.x; p0.y = k * (p0.x - p1.x) + p1.y; } else { k = (p2.y - p1.y) / (p2.x - p1.x); k1 = (p4.y- p3.y) / (p4.x - p3.x); p0.x = (p3.y-p1.y+k*p1.x-k1*p3.x) / (k - k1); p0.y = k * (p0.x - p1.x) + p1.y; } return 1; } bool lineBesideRectangle(Point p1, Point p2, Rectangle rec) { Vector v0, v1, v2, v3, v4; double c1, c2, c3, c4; v0.x = p2.x - p1.x; v0.y = p2.y - p1.y; v1.x = rec.p1.x - p1.x; v1.y = rec.p1.y - p1.y; v2.x = rec.p2.x - p1.x; v2.y = rec.p2.y - p1.y; v3.x = rec.p3.x - p1.x; v3.y = rec.p3.y - p1.y; v4.x = rec.p4.x - p1.x; v4.y = rec.p4.y - p1.y; c1 = cross(v0, v1); c2 = cross(v0, v2); c3 = cross(v0, v3); c4 = cross(v0, v4); if (c1*c2<-EPS || c1*c3<-EPS || c1*c4<-EPS || c2*c3<-EPS || c2*c4<-EPS || c3*c4<-EPS) return 0; return 1; } bool segmentOutsideRectangle(Point p1, Point p2, Rectangle rec) { Point p0; Vector v1, v2, v3, v4; double d1, d2; if (pointInsideRectangle(p1, rec)) return 0; if (pointInsideRectangle(p2, rec)) return 0; if (lineBesideRectangle(p1, p2, rec)) return 1; if (getIntersectPoint(p0, p1, p2, rec.p1, rec.p2)) { v1.x = p0.x - p1.x; v1.y = p0.y - p1.y; v2.x = p0.x - p2.x; v2.y = p0.y - p2.y; v3.x = p0.x - rec.p1.x; v3.y = p0.y - rec.p1.y; v4.x = p0.x - rec.p2.x; v4.y = p0.y - rec.p2.y; d1 = dot(v1, v2); d2 = dot(v3, v4); if (d1<-EPS && d2<-EPS) return 0; } if (getIntersectPoint(p0, p1, p2, rec.p2, rec.p3)) { v1.x = p0.x - p1.x; v1.y = p0.y - p1.y; v2.x = p0.x - p2.x; v2.y = p0.y - p2.y; v3.x = p0.x - rec.p2.x; v3.y = p0.y - rec.p2.y; v4.x = p0.x - rec.p3.x; v4.y = p0.y - rec.p3.y; d1 = dot(v1, v2); d2 = dot(v3, v4); if (d1<-EPS && d2<-EPS) return 0; } if (getIntersectPoint(p0, p1, p2, rec.p3, rec.p4)) { v1.x = p0.x - p1.x; v1.y = p0.y - p1.y; v2.x = p0.x - p2.x; v2.y = p0.y - p2.y; v3.x = p0.x - rec.p3.x; v3.y = p0.y - rec.p3.y; v4.x = p0.x - rec.p4.x; v4.y = p0.y - rec.p4.y; d1 = dot(v1, v2); d2 = dot(v3, v4); if (d1<-EPS && d2<-EPS) return 0; } if (getIntersectPoint(p0, p1, p2, rec.p4, rec.p1)) { v1.x = p0.x - p1.x; v1.y = p0.y - p1.y; v2.x = p0.x - p2.x; v2.y = p0.y - p2.y; v3.x = p0.x - rec.p4.x; v3.y = p0.y - rec.p4.y; v4.x = p0.x - rec.p1.x; v4.y = p0.y - rec.p1.y; d1 = dot(v1, v2); d2 = dot(v3, v4); if (d1<-EPS && d2<-EPS) return 0; } if (getIntersectPoint(p0, p1, p2, rec.p1, rec.p3)) { v1.x = p0.x - p1.x; v1.y = p0.y - p1.y; v2.x = p0.x - p2.x; v2.y = p0.y - p2.y; v3.x = p0.x - rec.p1.x; v3.y = p0.y - rec.p1.y; v4.x = p0.x - rec.p3.x; v4.y = p0.y - rec.p3.y; d1 = dot(v1, v2); d2 = dot(v3, v4); if (d1<-EPS && d2<-EPS) return 0; } if (getIntersectPoint(p0, p1, p2, rec.p2, rec.p4)) { v1.x = p0.x - p1.x; v1.y = p0.y - p1.y; v2.x = p0.x - p2.x; v2.y = p0.y - p2.y; v3.x = p0.x - rec.p2.x; v3.y = p0.y - rec.p2.y; v4.x = p0.x - rec.p4.x; v4.y = p0.y - rec.p4.y; d1 = dot(v1, v2); d2 = dot(v3, v4); if (d1<-EPS && d2<-EPS) return 0; } return 1; } double getDistance(Point p1, Point p2) { return sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y)); } double min(double a,double b) { return a<b?a:b; } void Dijkstra() { dis[4*n] = 0; bool vist[100] = {0}; int id; int i,k; double mind; for (k=0;k<=4*n+1;k++) { mind=INF; id=-1; for(i =0;i<=4*n+1; i++) { if(dis[i]<mind&&!vist[i]) { mind=dis[i]; id=i; } } if(id==-1) return; vist[id] = 1; for (i=0;i<=4*n+1;i++) { if(vist[i]) continue; dis[i]=min(dis[i],dis[id]+path[id][i]); } } } int main() { // freopen("a.txt","r",stdin); bool flag; int i,j,k; cin>>n; scanf("%lf%lf%lf%lf", &s.x, &s.y, &t.x, &t.y); for(i=0;i<n;i++) { cin>>p[4*i].x>>p[4*i].y>>p[4*i+1].x>>p[4*i+1].y>>p[4*i+2].x>>p[4*i+2].y; getRect(rec[i],p[4*i],p[4*i+1],p[4*i+2],p[4*i+3]); } for(i=0;i<=4*n+1;i++) { dis[i]=INF; for(j=0;j<=4*n+1;j++) path[i][j]=path[j][i]=INF; } for(i=0;i<4*n;i++) { flag=1; for(j=0;j<n&&flag;j++) { if(flag&&!segmentOutsideRectangle(s,p[i],rec[j])) flag=0; } if(flag) path[4*n][i]=path[i][4*n]=getDistance(s,p[i]); flag=1; for(j=0;j<n&&flag;j++) { if(flag&&!segmentOutsideRectangle(t,p[i],rec[j])) flag=0; } if(flag) path[4*n+1][i]=path[i][4*n+1]=getDistance(t,p[i]); } flag=1; for(i=0;i<n&&flag;i++) { if(flag&&!segmentOutsideRectangle(s,t,rec[i])) flag=0; } if(flag) path[4*n][4*n+1]=path[4*n+1][4*n]=getDistance(s,t); for(i=0;i<4*n;i++) { for(j=0;j<4*n;j++) { flag=1; for(k=0;k<n&&flag;k++) { if(!segmentOutsideRectangle(p[i],p[j],rec[k])) flag=0; } if(flag) path[i][j]=path[j][i]=getDistance(p[i],p[j]); } } Dijkstra(); printf("%.2f\n",dis[4*n+1]); return 0; }