Treasure Hunt
阿新 • • 發佈:2018-11-08
Treasure Hunt
http://poj.org/problem?id=1066
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8233 | Accepted: 3402 |
Description
Archeologists from the Antiquities and Curios Museum (ACM) have flown to Egypt to examine the great pyramid of Key-Ops. Using state-of-the-art technology they are able to determine that the lower floor of the pyramid is constructed from a series of straightline walls, which intersect to form numerous enclosed chambers. Currently, no doors exist to allow access to any chamber. This state-of-the-art technology has also pinpointed the location of the treasure room. What these dedicated (and greedy) archeologists want to do is blast doors through the walls to get to the treasure room. However, to minimize the damage to the artwork in the intervening chambers (and stay under their government grant for dynamite) they want to blast through the minimum number of doors. For structural integrity purposes, doors should only be blasted at the midpoint of the wall of the room being entered. You are to write a program which determines this minimum number of doors.An example is shown below:
Input
The input will consist of one case. The first line will be an integer n (0 <= n <= 30) specifying number of interior walls, followed by n lines containing integer endpoints of each wall x1 y1 x2 y2 . The 4 enclosing walls of the pyramid have fixed endpoints at (0,0); (0,100); (100,100) and (100,0) and are not included in the list of walls. The interior walls always span from one exterior wall to another exterior wall and are arranged such that no more than two walls intersect at any point. You may assume that no two given walls coincide. After the listing of the interior walls there will be one final line containing the floating point coordinates of the treasure in the treasure room (guaranteed not to lie on a wall).Output
Sample Input
7 20 0 37 100 40 0 76 100 85 0 0 75 100 90 0 90 0 71 100 61 0 14 100 38 100 47 47 100 54.5 55.4
Sample Output
Number of doors = 2
Source
East Central North America 1999
列舉邊界上的點,要注意,列舉的步長為1會wa,步長要0.5= =
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 18 double hypot(double x,double y){ 19 return sqrt(x*x+y*y); 20 } 21 22 inline double sqr(double x){return x*x;} 23 struct Point{ 24 double x,y; 25 Point(){} 26 Point(double _x,double _y){ 27 x=_x; 28 y=_y; 29 } 30 void input(){ 31 scanf("%lf %lf",&x,&y); 32 } 33 void output(){ 34 printf("%.2f %.2f\n",x,y); 35 } 36 bool operator == (const Point &b)const{ 37 return sgn(x-b.x) == 0 && sgn(y-b.y)== 0; 38 } 39 bool operator < (const Point &b)const{ 40 return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x; 41 } 42 Point operator - (const Point &b)const{ 43 return Point(x-b.x,y-b.y); 44 } 45 //叉積 46 double operator ^ (const Point &b)const{ 47 return x*b.y-y*b.x; 48 } 49 //點積 50 double operator * (const Point &b)const{ 51 return x*b.x+y*b.y; 52 } 53 //返回長度 54 double len(){ 55 return hypot(x,y); 56 } 57 //返回長度的平方 58 double len2(){ 59 return x*x+y*y; 60 } 61 //返回兩點的距離 62 double distance(Point p){ 63 return hypot(x-p.x,y-p.y); 64 } 65 Point operator + (const Point &b)const{ 66 return Point(x+b.x,y+b.y); 67 } 68 Point operator * (const double &k)const{ 69 return Point(x*k,y*k); 70 } 71 Point operator / (const double &k)const{ 72 return Point(x/k,y/k); 73 } 74 75 //計算pa和pb的夾角 76 //就是求這個點看a,b所成的夾角 77 ///LightOJ1202 78 double rad(Point a,Point b){ 79 Point p=*this; 80 return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p))); 81 } 82 //化為長度為r的向量 83 Point trunc(double r){ 84 double l=len(); 85 if(!sgn(l)) return *this; 86 r/=l; 87 return Point(x*r,y*r); 88 } 89 //逆時針轉90度 90 Point rotleft(){ 91 return Point(-y,x); 92 } 93 //順時針轉90度 94 Point rotright(){ 95 return Point(y,-x); 96 } 97 //繞著p點逆時針旋轉angle 98 Point rotate(Point p,double angle){ 99 Point v=(*this) -p; 100 double c=cos(angle),s=sin(angle); 101 return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); 102 } 103 }; 104 105 struct Line{ 106 Point s,e; 107 Line(){} 108 Line(Point _s,Point _e){ 109 s=_s; 110 e=_e; 111 } 112 bool operator==(Line v){ 113 return (s==v.s)&&(e==v.e); 114 } 115 //根據一個點和傾斜角angle確定直線,0<=angle<pi 116 Line(Point p,double angle){ 117 s=p; 118 if(sgn(angle-PI/2)==0){ 119 e=(s+Point(0,1)); 120 } 121 else{ 122 e=(s+Point(1,tan(angle))); 123 } 124 } 125 //ax+by+c=0; 126 Line(double a,double b,double c){ 127 if(sgn(a)==0){ 128 s=Point(0,-c/b); 129 e=Point(1,-c/b); 130 } 131 else if(sgn(b)==0){ 132 s=Point(-c/a,0); 133 e=Point(-c/a,1); 134 } 135 else{ 136 s=Point(0,-c/b); 137 e=Point(1,(-c-a)/b); 138 } 139 } 140 void input(){ 141 s.input(); 142 e.input(); 143 } 144 void adjust(){ 145 if(e<s) swap(s,e); 146 } 147 //求線段長度 148 double length(){ 149 return s.distance(e); 150 } 151 //返回直線傾斜角 0<=angle<pi 152 double angle(){ 153 double k=atan2(e.y-s.y,e.x-s.x); 154 if(sgn(k)<0) k+=PI; 155 if(sgn(k-PI)==0) k-=PI; 156 return k; 157 } 158 //點和直線的關係 159 //1 在左側 160 //2 在右側 161 //3 在直線上 162 int relation(Point p){ 163 int c=sgn((p-s)^(e-s)); 164 if(c<0) return 1; 165 else if(c>0) return 2; 166 else return 3; 167 } 168 //點線上段上的判斷 169 bool pointonseg(Point p){ 170 return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0; 171 } 172 //兩向量平行(對應直線平行或重合) 173 bool parallel(Line v){ 174 return sgn((e-s)^(v.e-v.s))==0; 175 } 176 //兩線段相交判斷 177 //2 規範相交 178 //1 非規範相交 179 //0 不相交 180 int segcrossseg(Line v){ 181 int d1=sgn((e-s)^(v.s-s)); 182 int d2=sgn((e-s)^(v.e-s)); 183 int d3=sgn((v.e-v.s)^(s-v.s)); 184 int d4=sgn((v.e-v.s)^(e-v.s)); 185 if((d1^d2)==-2&&(d3^d4)==-2) return 2; 186 return (d1==0&&sgn((v.s-s)*(v.s-e))<=0|| 187 d2==0&&sgn((v.e-s)*(v.e-e))<=0|| 188 d3==0&&sgn((s-v.s)*(s-v.e))<=0|| 189 d4==0&&sgn((e-v.s)*(e-v.e))<=0); 190 } 191 //直線和線段相交判斷 192 //-*this line -v seg 193 //2 規範相交 194 //1 非規範相交 195 //0 不相交 196 int linecrossseg(Line v){ 197 int d1=sgn((e-s)^(v.s-s)); 198 int d2=sgn((e-s)^(v.e-s)); 199 if((d1^d2)==-2) return 2; 200 return (d1==0||d2==0); 201 } 202 //兩直線關係 203 //0 平行 204 //1 重合 205 //2 相交 206 int linecrossline(Line v){ 207 if((*this).parallel(v)) 208 return v.relation(s)==3; 209 return 2; 210 } 211 //求兩直線的交點 212 //要保證兩直線不平行或重合 213 Point crosspoint(Line v){ 214 double a1=(v.e-v.s)^(s-v.s); 215 double a2=(v.e-v.s)^(e-v.s); 216 return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1)); 217 } 218 //點到直線的距離 219 double dispointtoline(Point p){ 220 return fabs((p-s)^(e-s))/length(); 221 } 222 //點到線段的距離 223 double dispointtoseg(Point p){ 224 if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0) 225 return min(p.distance(s),p.distance(e)); 226 return dispointtoline(p); 227 } 228 //返回線段到線段的距離 229 //前提是兩線段不相交,相交距離就是0了 230 double dissegtoseg(Line v){ 231 return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e))); 232 } 233 //返回點P在直線上的投影 234 Point lineprog(Point p){ 235 return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2())); 236 } 237 //返回點P關於直線的對稱點 238 Point symmetrypoint(Point p){ 239 Point q=lineprog(p); 240 return Point(2*q.x-p.x,2*q.y-p.y); 241 } 242 }; 243 244 Line L[1005]; 245 int n; 246 247 bool Check(Line a,Line b){ 248 if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false; 249 if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false; 250 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 251 &&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) 252 return true; 253 else return false; 254 } 255 256 257 double mp[115][115]; 258 259 int co; 260 261 int panduan(Line a){ 262 int sum=0; 263 for(int i=1;i<=n;i++){ 264 if(Check(a,L[i])){ 265 sum++; 266 } 267 } 268 return sum; 269 } 270 271 int main(){ 272 273 while(~scanf("%d",&n)){ 274 for(int i=1;i<=n;i++){ 275 scanf("%lf %lf %lf %lf",&L[i].s.x,&L[i].s.y,&L[i].e.x,&L[i].e.y); 276 } 277 int ans=0x3f3f3f3f; 278 Point goal; 279 scanf("%lf %lf",&goal.x,&goal.y); 280 Line tmp; 281 tmp.s=goal; 282 for(double i=0;i+eps<=100;i+=0.5){ 283 tmp.e.x=0,tmp.e.y=i; 284 ans=min(ans,panduan(tmp)); 285 tmp.e.x=i,tmp.e.y=0; 286 ans=min(ans,panduan(tmp)); 287 tmp.e.x=100,tmp.e.y=i; 288 ans=min(ans,panduan(tmp)); 289 tmp.e.x=i,tmp.e.y=100; 290 ans=min(ans,panduan(tmp)); 291 } 292 printf("Number of doors = %d\n",ans+1); 293 } 294 295 return 0; 296 }View Code