起点和终点给出,让计算他的最短路径,由于都是正权,所以用dijkstra。每两个点之间的距离都可以求出来,但是有的两个点之间有墙,所以这个时候是不能把距离加到临界矩阵中的。所以用判断两线段相交的方法,我看书看了好长时间,没怎么看懂,直接就把函数移过来了,等以后学计算几何的时候在弄他吧。。
#include<iostream> #include<cstdio> #include<cmath> #include<iomanip> using namespace std; #define INF 999999999 struct point { double x,y; int o; } points[75]; //最多74个点 struct wall { struct point a[4]; } walls[19]; //最多18堵墙 typedef struct point Point; int dblcmp(double d) { if( fabs(d) < 1e-8 ) return 0; return (d>0)?1:-1; } double det(double x1,double y1,double x2,double y2) { return x1*y2-x2*y1;}/ double cross(Point a,Point b,Point c) {return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);} int SCS(Point a,Point b,Point c,Point d) { return (dblcmp(cross(a,c,d))^dblcmp(cross(b,c,d))) == -2 && (dblcmp(cross(c,a,b))^dblcmp(cross(d,a,b))) == -2; } //以上几个函数是用来判断线段规范相交的 int main(void) { int N; double x; double mat[75][75]; int used[75]; double dist[75],min; int now,flag; while( cin >> N && N != -1 ) { points[1].x = 0;points[1].y = 5;points[1].o = 0; points[2].x = 10;points[2].y = 5;points[2].o = N+1; for( int i = 1,j = 2; i <= N; i++ ) { cin >> x; for( int k = 0; k <= 3; k++ ) { walls[i].a[k].x = x; cin >> walls[i].a[k].y; walls[i].a[k].o = i; points[++j] = walls[i].a[k]; } } //以上是墙和点的输入过程 N = 2 + 4*N; for( int i = 1; i <= N; i++ ) { for( int j = 1; j <= N; j++ ) { if( i == j ) {mat[i][j] = INF;continue;} if( points[i].o == points[j].o ) {mat[i][j] = INF;continue;} mat[i][j] = sqrt( (points[i].x - points[j].x) * (points[i].x - points[j].x) + (points[i].y - points[j].y) * (points[i].y - points[j].y) ); } }//求出每两点间的距离 for( int i = 1; i <= N; i++ ) for( int j = 1; j <= N; j++ ) { if( mat[i][j] == INF ) continue; flag = 1; for( int k = points[i].o + 1; k < points[j].o; k++ ) { if( SCS(points[i],points[j],walls[k].a[0],walls[k].a[1]) || SCS(points[i],points[j],walls[k].a[2],walls[k].a[3]) ) continue; else flag = 0; } if( !flag ) mat[i][j] = INF; }//把与墙相交的找出来mat值赋为INF for( int i = 1; i <= N; i++) { dist[i] = INF; used[i] = 0; } dist[now = 1] = 0; //dijkstra used[now] = 1; for(int i = 1; i < N; i++ ) { for( int j = 1; j <= N; j++ ) if( dist[j] > dist[now] + mat[now][j] ) dist[j] = dist[now] + mat[now][j]; min = INF; for( int j = 1; j <= N; j++ ) if( !used[j] && dist[j] < min ) min = dist[now = j]; used[now] = 1; } printf("%.2lf/n",dist[2];//c++输出搞死我了,直接换c } return 0; }