poj 1556 线段相交加最短路
题意:在平面直角坐标系上有一个10*10的正方形房间,房间中有n堵平行y方向的墙,每堵墙上有两扇门,
问从房间最左边的(0,5)处,通过门,到达房间最右边的(10,5)处的最短距离
题解:考虑从起始点,若沿x轴走则可以一直走到被墙堵住为止,此时其需要走到堵住它的墙的门的端点,一定可以转化成更早就从某一个门的端点开始走距离更短,可以考虑成两点AB之间,不能直接用线段相连,那么是一直走平行于X轴的直线然后转折到另一个点,还是直接走更趋近于AB的斜线然后转折,明显后一种距离更短。
把起点和终点和门上所有端点设想为图上的点,每两个点之间建边,如果两点之间会被墙阻隔则设为无穷大,因为数据很小,可以随便遍历,不用太考虑时间复杂度
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #include <iostream> 6 #include <map> 7 #include <queue> 8 #include <stack> 9 #include <cmath> 10 //#pragma comment(linker, "/STACK:102400000,102400000") 11 using namespace std; 12 #define PF(x) cout << "debug: " << x << " "; 13 #define EL cout << endl; 14 #define PC(x) puts(x); 15 typedef long long ll; 16 #define CLR(x, v) sizeof (x, v, sizeof(x)) 17 using namespace std; 18 const int INF = 0x5f5f5f5f; 19 const int N= 2e5 + 10; 20 const int mod=1e9 + 7; 21 const int maxn = 100; 22 const double eps = 1e-8; 23 const double PI = acos(-1.0); 24 int t; 25 int sgn(double x){ 26 if(fabs(x) < eps) return 0; 27 if(x < 0) return -1; 28 else return 1; 29 30 } 31 struct Point{ 32 double x,y; 33 Point() { } 34 Point(double _x,double _y){ 35 x = _x,y = _y; 36 } 37 Point operator - (const Point &b) const{ //相对坐标 38 return Point(x - b.x,y - b.y); 39 } 40 double operator ^(const Point &b)const{//叉积 41 return x*b.y - y*b.x; 42 } 43 double operator *(const Point &b)const{//点积 44 return x*b.x + y*b.y; 45 } 46 void transXY(double B){ 47 double tx = x,ty = y; 48 x = tx*cos(B) - ty*sin(B); 49 y = tx*sin(B) + ty*cos(B); 50 } 51 }; 52 struct Line{ 53 Point s,e; 54 Line() { } 55 Line (Point _s,Point _e){ 56 s = _s,e = _e; 57 } 58 //两直线相交求交点 59 //第一个值为0表示直线重合,为1表示平行,为2是相交 60 //只有第一个值为2时交点才有意义 61 pair<int,Point> operator &(const Line &b) const{ 62 Point res = s; 63 if(sgn((s-e)^(b.s-b.e)) == 0){ 64 if(sgn((s-b.e)^(b.s-b.e)) == 0) 65 return make_pair(0,res);//重合 66 else 67 return make_pair(1,res); 68 } 69 double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); 70 res.x += (e.x-s.x)*t; 71 res.y += (e.y-s.y)*t; 72 return make_pair(2,res); 73 } 74 }; 75 double dist(Point a,Point b){ 76 return sqrt((b-a)*(b-a)); 77 } 78 bool Seg_inter_line(Line l1,Line l2){//判断直线l1与线段l2是否相交 79 return sgn((l2.s - l1.e) ^ (l1.s-l1.e)) * sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0; 80 } 81 bool inter(Line l1,Line l2){ 82 return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && 83 max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && 84 max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && 85 max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && 86 sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0&& 87 sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0; 88 89 } 90 int n,cntl,cntp; 91 double gra[maxn][maxn]; 92 Line line[maxn]; 93 Point pt[maxn]; 94 void flyod(){ 95 for(int k = 1;k <= cntp;k++) 96 for(int i = 1;i <= cntp;i++) 97 for(int j = 1;j <= cntp;j++) 98 gra[i][j] = min(gra[i][j],gra[i][k]+gra[k][j]); 99 100 } 101 bool cek(Line l){ 102 for(int i = 1;i <= cntl;i++){ 103 if(dist(line[i].s,l.s) == 0||dist(line[i].s,l.e) == 0||dist(line[i].e,l.s) == 0||dist(line[i].e,l.e) == 0) 104 continue; 105 if(inter(l,line[i])) 106 return false; 107 } 108 return true; 109 } 110 int main() 111 { 112 // freopen("in.txt","r",stdin); 113 while(~scanf("%d",&n)){ 114 if(n == -1) 115 break; 116 double x,h1,h2,h3,h4; 117 cntl = 0,cntp = 2; 118 for(int i = 1;i < 100;i++) 119 for(int j = 1;j <100;j++) 120 gra[i][j] = 10000.0; 121 pt[1] = Point(0,5); 122 pt[2] = Point(10,5); 123 for(int i = 1;i <= n;i++){ 124 scanf("%lf%lf%lf%lf%lf",&x,&h1,&h2,&h3,&h4); 125 line[++cntl] = Line(Point(x,0),Point(x,h1)); 126 line[++cntl] = Line(Point(x,h2),Point(x,h3)); 127 line[++cntl] = Line(Point(x,h4),Point(x,10)); 128 pt[++cntp] = Point(x,h1); 129 pt[++cntp] = Point(x,h2); 130 pt[++cntp] = Point(x,h3); 131 pt[++cntp] = Point(x,h4); 132 } 133 for(int i = 1;i <= cntp;i++) 134 for(int j = i;j <= cntp;j++){ 135 if(i == j){ 136 gra[i][i] = 0; 137 continue; 138 } 139 Line l = Line(pt[i],pt[j]); 140 if(cek(l)){ 141 gra[i][j] = dist(pt[i],pt[j]); 142 gra[j][i] = gra[i][j]; 143 } 144 145 } 146 flyod(); 147 printf("%.2f\n",gra[1][2]); 148 } 149 return 0; 150 }