The Doors(几何+最短路,好题)
The Doors
http://poj.org/problem?id=1556
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 10466 | Accepted: 3891 |
Description
You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length.
Input
The input data for the illustrated chamber would appear as follows.
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
Output
The output should contain one line of output for each chamber. The line should contain the minimal path length rounded to two decimal places past the decimal point, and always showing the two decimal places past the decimal point. The line should contain no blanks.
Sample Input
1 5 4 6 7 8 2 4 2 7 8 9 7 3 4.5 6 7 -1
Sample Output
10.00 10.06
Source
有18堵墙!!!因为没看清这个疯狂爆RE
poj上交C++会CE,要自己写hypot函数
double hypot(double x,double y){
return sqrt(x*x+y*y);
}
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 #include<algorithm> 7 using namespace std; 8 const double eps=1e-8; 9 const double INF=1e20; 10 const double PI=acos(-1.0); 11 const int maxp=1010; 12 int sgn(double x){ 13 if(fabs(x)<eps) return 0; 14 if(x<0) return -1; 15 else return 1; 16 } 17 inline double sqr(double x){return x*x;} 18 struct Point{ 19 double x,y; 20 Point(){} 21 Point(double _x,double _y){ 22 x=_x; 23 y=_y; 24 } 25 void input(){ 26 scanf("%lf %lf",&x,&y); 27 } 28 void output(){ 29 printf("%.2f %.2f\n",x,y); 30 } 31 bool operator == (const Point &b)const{ 32 return sgn(x-b.x) == 0 && sgn(y-b.y)== 0; 33 } 34 bool operator < (const Point &b)const{ 35 return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x; 36 } 37 Point operator - (const Point &b)const{ 38 return Point(x-b.x,y-b.y); 39 } 40 //叉积 41 double operator ^ (const Point &b)const{ 42 return x*b.y-y*b.x; 43 } 44 //点积 45 double operator * (const Point &b)const{ 46 return x*b.x+y*b.y; 47 } 48 //返回长度 49 double len(){ 50 return hypot(x,y); 51 } 52 //返回长度的平方 53 double len2(){ 54 return x*x+y*y; 55 } 56 //返回两点的距离 57 double distance(Point p){ 58 return hypot(x-p.x,y-p.y); 59 } 60 Point operator + (const Point &b)const{ 61 return Point(x+b.x,y+b.y); 62 } 63 Point operator * (const double &k)const{ 64 return Point(x*k,y*k); 65 } 66 Point operator / (const double &k)const{ 67 return Point(x/k,y/k); 68 } 69 70 //计算pa和pb的夹角 71 //就是求这个点看a,b所成的夹角 72 ///LightOJ1202 73 double rad(Point a,Point b){ 74 Point p=*this; 75 return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p))); 76 } 77 //化为长度为r的向量 78 Point trunc(double r){ 79 double l=len(); 80 if(!sgn(l)) return *this; 81 r/=l; 82 return Point(x*r,y*r); 83 } 84 //逆时针转90度 85 Point rotleft(){ 86 return Point(-y,x); 87 } 88 //顺时针转90度 89 Point rotright(){ 90 return Point(y,-x); 91 } 92 //绕着p点逆时针旋转angle 93 Point rotate(Point p,double angle){ 94 Point v=(*this) -p; 95 double c=cos(angle),s=sin(angle); 96 return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); 97 } 98 }; 99 100 struct Line{ 101 Point s,e; 102 Line(){} 103 Line(Point _s,Point _e){ 104 s=_s; 105 e=_e; 106 } 107 bool operator==(Line v){ 108 return (s==v.s)&&(e==v.e); 109 } 110 //根据一个点和倾斜角angle确定直线,0<=angle<pi 111 Line(Point p,double angle){ 112 s=p; 113 if(sgn(angle-PI/2)==0){ 114 e=(s+Point(0,1)); 115 } 116 else{ 117 e=(s+Point(1,tan(angle))); 118 } 119 } 120 //ax+by+c=0; 121 Line(double a,double b,double c){ 122 if(sgn(a)==0){ 123 s=Point(0,-c/b); 124 e=Point(1,-c/b); 125 } 126 else if(sgn(b)==0){ 127 s=Point(-c/a,0); 128 e=Point(-c/a,1); 129 } 130 else{ 131 s=Point(0,-c/b); 132 e=Point(1,(-c-a)/b); 133 } 134 } 135 void input(){ 136 s.input(); 137 e.input(); 138 } 139 void adjust(){ 140 if(e<s) swap(s,e); 141 } 142 //求线段长度 143 double length(){ 144 return s.distance(e); 145 } 146 //返回直线倾斜角 0<=angle<pi 147 double angle(){ 148 double k=atan2(e.y-s.y,e.x-s.x); 149 if(sgn(k)<0) k+=PI; 150 if(sgn(k-PI)==0) k-=PI; 151 return k; 152 } 153 //点和直线的关系 154 //1 在左侧 155 //2 在右侧 156 //3 在直线上 157 int relation(Point p){ 158 int c=sgn((p-s)^(e-s)); 159 if(c<0) return 1; 160 else if(c>0) return 2; 161 else return 3; 162 } 163 //点在线段上的判断 164 bool pointonseg(Point p){ 165 return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0; 166 } 167 //两向量平行(对应直线平行或重合) 168 bool parallel(Line v){ 169 return sgn((e-s)^(v.e-v.s))==0; 170 } 171 //两线段相交判断 172 //2 规范相交 173 //1 非规范相交 174 //0 不相交 175 int segcrossseg(Line v){ 176 int d1=sgn((e-s)^(v.s-s)); 177 int d2=sgn((e-s)^(v.e-s)); 178 int d3=sgn((v.e-v.s)^(s-v.s)); 179 int d4=sgn((v.e-v.s)^(e-v.s)); 180 if((d1^d2)==-2&&(d3^d4)==-2) return 2; 181 return (d1==0&&sgn((v.s-s)*(v.s-e))<=0|| 182 d2==0&&sgn((v.e-s)*(v.e-e))<=0|| 183 d3==0&&sgn((s-v.s)*(s-v.e))<=0|| 184 d4==0&&sgn((e-v.s)*(e-v.e))<=0); 185 } 186 //直线和线段相交判断 187 //-*this line -v seg 188 //2 规范相交 189 //1 非规范相交 190 //0 不相交 191 int linecrossseg(Line v){ 192 int d1=sgn((e-s)^(v.s-s)); 193 int d2=sgn((e-s)^(v.e-s)); 194 if((d1^d2)==-2) return 2; 195 return (d1==0||d2==0); 196 } 197 //两直线关系 198 //0 平行 199 //1 重合 200 //2 相交 201 int linecrossline(Line v){ 202 if((*this).parallel(v)) 203 return v.relation(s)==3; 204 return 2; 205 } 206 //求两直线的交点 207 //要保证两直线不平行或重合 208 Point crosspoint(Line v){ 209 double a1=(v.e-v.s)^(s-v.s); 210 double a2=(v.e-v.s)^(e-v.s); 211 return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1)); 212 } 213 //点到直线的距离 214 double dispointtoline(Point p){ 215 return fabs((p-s)^(e-s))/length(); 216 } 217 //点到线段的距离 218 double dispointtoseg(Point p){ 219 if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0) 220 return min(p.distance(s),p.distance(e)); 221 return dispointtoline(p); 222 } 223 //返回线段到线段的距离 224 //前提是两线段不相交,相交距离就是0了 225 double dissegtoseg(Line v){ 226 return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e))); 227 } 228 //返回点P在直线上的投影 229 Point lineprog(Point p){ 230 return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2())); 231 } 232 //返回点P关于直线的对称点 233 Point symmetrypoint(Point p){ 234 Point q=lineprog(p); 235 return Point(2*q.x-p.x,2*q.y-p.y); 236 } 237 }; 238 239 Line L[1005]; 240 int n; 241 242 bool Check(Line a,Line b){ 243 if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false; 244 if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false; 245 if(sgn(max(a.s.x,a.e.x)-min(b.s.x,b.e.x))>=0&&sgn(max(b.s.x,b.e.x)-min(a.s.x,a.e.x))>=0 246 &&sgn(max(a.s.y,a.e.y)-min(b.s.y,b.e.y))>=0&&sgn(max(b.s.y,b.e.y)-min(a.s.y,a.e.y))>=0) 247 return true; 248 else return false; 249 } 250 251 252 double mp[115][115]; 253 254 int co; 255 256 void panduan(Line a,int xx,int yy){ 257 if(a.s.y==0||a.s.y==10||a.e.y==0||a.e.y==10) return; 258 for(int i=1;i<co;i++){ 259 if(i!=(xx+1)/2&&i!=(yy+1)/2){ 260 if(Check(a,L[i])){ 261 return; 262 } 263 } 264 } 265 //cout<<xx<<" "<<yy<<" "<<a.length()<<endl; 266 267 mp[xx][yy]=mp[yy][xx]=a.length(); 268 } 269 270 int main(){ 271 while(~scanf("%d",&n)){ 272 if(n==-1) break; 273 double x,y1,y2,y3,y4; 274 co=1; 275 for(int i=0;i<115;i++){ 276 for(int j=0;j<115;j++){ 277 mp[i][j]=INF; 278 } 279 } 280 Point s,e; 281 s.x=0,s.y=5; 282 e.x=10,e.y=5; 283 //起点为0,终点为co 284 for(int i=1;i<=n;i++){ 285 scanf("%lf %lf %lf %lf %lf",&x,&y1,&y2,&y3,&y4); 286 L[co].s.x=x,L[co].s.y=0,L[co].e.x=x,L[co++].e.y=y1; 287 L[co].s.x=x,L[co].s.y=y2,L[co].e.x=x,L[co++].e.y=y3; 288 L[co].s.x=x,L[co].s.y=y4,L[co].e.x=x,L[co++].e.y=10; 289 } 290 291 Line tmp; 292 int j; 293 //不包括起点和终点的建图 294 for(int i=1;i<co;i++){ 295 for(int j=i+1;j<co;j++){ 296 tmp.s=L[i].s,tmp.e=L[j].s; 297 panduan(tmp,(i-1)*2+1,(j-1)*2+1); 298 tmp.s=L[i].s,tmp.e=L[j].e; 299 panduan(tmp,(i-1)*2+1,(j-1)*2+2); 300 tmp.s=L[i].e,tmp.e=L[j].s; 301 panduan(tmp,(i-1)*2+2,(j-1)*2+1); 302 tmp.s=L[i].e,tmp.e=L[j].e; 303 panduan(tmp,(i-1)*2+2,(j-1)*2+2); 304 } 305 } 306 //加上起点和终点 307 for(int i=1;i<co;i++){ 308 tmp.s=s,tmp.e=L[i].s; 309 panduan(tmp,0,(i-1)*2+1); 310 tmp.s=s,tmp.e=L[i].e; 311 panduan(tmp,0,(i-1)*2+2); 312 tmp.s=e,tmp.e=L[i].s; 313 panduan(tmp,(i-1)*2+1,114); 314 tmp.s=e,tmp.e=L[i].e; 315 panduan(tmp,(i-1)*2+2,114); 316 } 317 tmp.s=s,tmp.e=e; 318 panduan(tmp,0,114); 319 for(int k=0;k<=114;k++) 320 for(int i=0;i<=114;i++) 321 for(int j=0;j<=114;j++) 322 if(mp[i][j]>mp[i][k]+mp[k][j]+eps) 323 mp[i][j]=mp[i][k]+mp[k][j]; 324 printf("%.2f\n",mp[0][114]); 325 } 326 return 0; 327 }
posted on 2018-11-08 10:30 Fighting_sh 阅读(252) 评论(0) 编辑 收藏 举报