题意:给出一个闭合折线上的一堆点(不按顺序),然后再给一个点P,要求判断P是否在闭合折线内
sol attempt1:一开始觉得是个模板题的,后来发现不对劲:
给出的点并不按照顺序。这样模板大法就不行了(geiline函数是按顺序建line的,会错乱掉)
sol attempt2:手艹大法:先建立好图形,然后再判断:
从点P向外引射线,若射线与图形的边相交奇数次,说明P在图形内。
PS:本题测试数据好像有点不对劲:
对于这组数据:
12 0 40 0 50 0 0 10 10 0 30 0 20 0 10 10 40 20 50 20 0 10 20 10 30 10 1
很容易画出图:
很容易发现绿色点P应该是INSIDE的,但是testdata是OUTSIDE
围观了下标程。。。好像是对于多组数据标程忘了初始化数组了。当时现场也并没有人过orz
附我的code:
1 #include<vector> 2 #include<list> 3 #include<map> 4 #include<set> 5 #include<deque> 6 #include<queue> 7 #include<stack> 8 #include<bitset> 9 #include<algorithm> 10 #include<functional> 11 #include<numeric> 12 #include<utility> 13 #include<iostream> 14 #include<sstream> 15 #include<iomanip> 16 #include<cstdio> 17 #include<cmath> 18 #include<cstdlib> 19 #include<cctype> 20 #include<string> 21 #include<cstring> 22 #include<cstdio> 23 #include<cmath> 24 #include<cstdlib> 25 #include<ctime> 26 #include<climits> 27 #include<complex> 28 #define mp make_pair 29 #define pb push_back 30 using namespace std; 31 const double eps=1e-8; 32 const double pi=acos(-1.0); 33 const double inf=1e20; 34 const int maxp=10010; //多边形内点的数量,注意按需求调整 35 36 int sgn(double x) 37 { 38 if (fabs(x)<eps) return 0; 39 if (x<0) return -1; 40 else return 1; 41 } 42 43 int dblcmp(double d) 44 { 45 if (fabs(d)<eps)return 0; 46 return d>eps?1:-1; 47 } 48 49 inline double sqr(double x){return x*x;} 50 struct point 51 { 52 double x,y; 53 point(){} 54 point(double _x,double _y): 55 x(_x),y(_y){}; 56 void input() 57 { 58 scanf("%lf%lf",&x,&y); 59 } 60 void output() 61 { 62 printf("%.2f %.2f\n",x,y); 63 } 64 bool operator==(point a)const 65 { 66 return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0; 67 } 68 bool operator<(point a)const 69 { 70 return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x; 71 } 72 73 point operator +(const point &b)const 74 { 75 return point(x+b.x,y+b.y); 76 } 77 point operator -(const point &b)const 78 { 79 return point(x-b.x,y-b.y); 80 } 81 point operator *(const double &k)const 82 { 83 return point(x*k,y*k); 84 } 85 point operator /(const double &k)const 86 { 87 return point(x/k,y/k); 88 } 89 double operator ^(const point &b)const 90 { 91 return x*b.y-y*b.x; 92 } 93 double operator *(const point &b)const 94 { 95 return x*b.x+y*b.y; 96 } 97 98 double len() 99 { 100 return hypot(x,y); 101 } 102 double len2() 103 { 104 return x*x+y*y; 105 } 106 double distance(point p) 107 { 108 return hypot(x-p.x,y-p.y); 109 } 110 point add(point p) 111 { 112 return point(x+p.x,y+p.y); 113 } 114 point sub(point p) 115 { 116 return point(x-p.x,y-p.y); 117 } 118 point mul(double b) 119 { 120 return point(x*b,y*b); 121 } 122 point div(double b) 123 { 124 return point(x/b,y/b); 125 } 126 double dot(point p) 127 { 128 return x*p.x+y*p.y; 129 } 130 double det(point p) 131 { 132 return x*p.y-y*p.x; 133 } 134 double rad(point a,point b) 135 { 136 point p=*this; 137 return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p)))); 138 } 139 point trunc(double r) 140 { 141 double l=len(); 142 if (!dblcmp(l))return *this; 143 r/=l; 144 return point(x*r,y*r); 145 } 146 point rotleft() 147 { 148 return point(-y,x); 149 } 150 point rotright() 151 { 152 return point(y,-x); 153 } 154 point rotate(point p,double angle)//绕点p逆时针旋转angle角度 155 { 156 point v=this->sub(p); 157 double c=cos(angle),s=sin(angle); 158 return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); 159 } 160 }; 161 162 struct line 163 { 164 point a,b; 165 line(){} 166 line(point _a,point _b) 167 { 168 a=_a; 169 b=_b; 170 } 171 bool operator==(line v) 172 { 173 return (a==v.a)&&(b==v.b); 174 } 175 //倾斜角angle 176 line(point p,double angle) 177 { 178 a=p; 179 if (dblcmp(angle-pi/2)==0) 180 { 181 b=a.add(point(0,1)); 182 } 183 else 184 { 185 b=a.add(point(1,tan(angle))); 186 } 187 } 188 //ax+by+c=0 189 line(double _a,double _b,double _c) 190 { 191 if (dblcmp(_a)==0) 192 { 193 a=point(0,-_c/_b); 194 b=point(1,-_c/_b); 195 } 196 else if (dblcmp(_b)==0) 197 { 198 a=point(-_c/_a,0); 199 b=point(-_c/_a,1); 200 } 201 else 202 { 203 a=point(0,-_c/_b); 204 b=point(1,(-_c-_a)/_b); 205 } 206 } 207 void input() 208 { 209 a.input(); 210 b.input(); 211 } 212 void adjust() 213 { 214 if (b<a)swap(a,b); 215 } 216 double length() 217 { 218 return a.distance(b); 219 } 220 double angle()//直线倾斜角 0<=angle<180 221 { 222 double k=atan2(b.y-a.y,b.x-a.x); 223 if (dblcmp(k)<0)k+=pi; 224 if (dblcmp(k-pi)==0)k-=pi; 225 return k; 226 } 227 //点和线段关系 228 //1 在逆时针 229 //2 在顺时针 230 //3 平行 231 int relation(point p) 232 { 233 int c=dblcmp(p.sub(a).det(b.sub(a))); 234 if (c<0)return 1; 235 if (c>0)return 2; 236 return 3; 237 } 238 bool pointonseg(point p) 239 { 240 return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0; 241 } 242 bool parallel(line v) 243 { 244 return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0; 245 } 246 //2 规范相交 247 //1 非规范相交 248 //0 不相交 249 int segcrossseg(line v) 250 { 251 int d1=dblcmp(b.sub(a).det(v.a.sub(a))); 252 int d2=dblcmp(b.sub(a).det(v.b.sub(a))); 253 int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a))); 254 int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a))); 255 if ((d1^d2)==-2&&(d3^d4)==-2)return 2; 256 return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0|| 257 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0|| 258 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0|| 259 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0); 260 } 261 int linecrossseg(line v)//*this seg v line 262 { 263 int d1=dblcmp(b.sub(a).det(v.a.sub(a))); 264 int d2=dblcmp(b.sub(a).det(v.b.sub(a))); 265 if ((d1^d2)==-2)return 2; 266 return (d1==0||d2==0); 267 } 268 //0 平行 269 //1 重合 270 //2 相交 271 int linecrossline(line v) 272 { 273 if ((*this).parallel(v)) 274 { 275 return v.relation(a)==3; 276 } 277 return 2; 278 } 279 point crosspoint(line v) 280 { 281 double a1=v.b.sub(v.a).det(a.sub(v.a)); 282 double a2=v.b.sub(v.a).det(b.sub(v.a)); 283 return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1)); 284 } 285 double dispointtoline(point p) 286 { 287 return fabs(p.sub(a).det(b.sub(a)))/length(); 288 } 289 double dispointtoseg(point p) 290 { 291 if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0) 292 { 293 return min(p.distance(a),p.distance(b)); 294 } 295 return dispointtoline(p); 296 } 297 point lineprog(point p) 298 { 299 return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2())); 300 } 301 point symmetrypoint(point p) 302 { 303 point q=lineprog(p); 304 return point(2*q.x-p.x,2*q.y-p.y); 305 } 306 }; 307 308 struct Vector:public point 309 { 310 Vector(){} 311 Vector(double a,double b) 312 { 313 x=a; y=b; 314 } 315 Vector(point _a,point _b) //a->b 316 { 317 double dx=_b.x-_a.x; 318 double dy=_b.y-_a.y; 319 x=dx; y=dy; 320 } 321 Vector(line v) 322 { 323 double dx=v.b.x-v.a.x; 324 double dy=v.b.y-v.a.y; 325 x=dx; y=dy; 326 } 327 double length() 328 { 329 return (sqrt(x*x+y*y)); 330 } 331 Vector Normal() 332 { 333 double L=sqrt(x*x+y*y); 334 Vector Vans=Vector(-y/L,x/L); 335 return Vans; 336 } 337 }; 338 339 struct polygon 340 { 341 int n; //the number of points 342 int nl; //the number of lines 343 point p[maxp]; //0..n-1 344 line l[maxp]; //0..nl-1 345 /* 346 void input(int X) 347 { 348 n=X; 349 nl=X; 350 for (int i=0;i<n;i++) 351 { 352 p[i].input(); 353 } 354 } 355 */ 356 void add(point q) 357 { 358 p[n++]=q; 359 } 360 /* 361 void getline() 362 { 363 for (int i=0;i<n;i++) 364 { 365 l[i]=line(p[i],p[(i+1)%n]); 366 } 367 } 368 */ 369 370 //3 点上 371 //2 边上 372 //1 内部 373 //0 外部 374 int relationpoint(point q) 375 { 376 int i,j; 377 for (i=0;i<n;i++) 378 { 379 if (p[i]==q)return 3; 380 } 381 //getline(); 382 for (i=0;i<nl;i++) 383 { 384 if (l[i].pointonseg(q))return 2; 385 } 386 int cnt=0; 387 for (i=0;i<n;i++) 388 { 389 j=(i+1)%n; 390 int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j]))); 391 int u=dblcmp(p[i].y-q.y); 392 int v=dblcmp(p[j].y-q.y); 393 if (k>0&&u<0&&v>=0)cnt++; 394 if (k<0&&v<0&&u>=0)cnt--; 395 } 396 return cnt!=0; 397 } 398 /* 399 //1 在多边形内长度为正 400 //2 相交或与边平行 401 //0 无任何交点 402 int relationline(line u) 403 { 404 int i,j,k=0; 405 //getline(); 406 for (i=0;i<nl;i++) 407 { 408 if (l[i].segcrossseg(u)==2)return 1; 409 if (l[i].segcrossseg(u)==1)k=1; 410 } 411 if (!k)return 0; 412 vector<point>vp; 413 for (i=0;i<nl;i++) 414 { 415 if (l[i].segcrossseg(u)) 416 { 417 if (l[i].parallel(u)) 418 { 419 vp.pb(u.a); 420 vp.pb(u.b); 421 vp.pb(l[i].a); 422 vp.pb(l[i].b); 423 continue; 424 } 425 vp.pb(l[i].crosspoint(u)); 426 } 427 } 428 sort(vp.begin(),vp.end()); 429 int sz=vp.size(); 430 for (i=0;i<sz-1;i++) 431 { 432 point mid=vp[i].add(vp[i+1]).div(2); 433 if (relationpoint(mid)==1)return 1; 434 } 435 return 2; 436 */ 437 }; 438 439 int k; 440 double X0,Y0; 441 line Line[10010]; 442 struct poi 443 { 444 int x; int y; 445 }a[10010]; 446 447 void xsort(int l,int r) 448 { 449 int i=l,j=r; 450 int mid=(l+r)/2; 451 while(i<j) 452 { 453 while((a[i].x<a[mid].x)||((a[i].x==a[mid].x)&&(a[i].y<a[mid].y))) 454 i++; 455 while((a[j].x>a[mid].x)||((a[j].x==a[mid].x)&&(a[j].y>a[mid].y))) 456 j--; 457 if (i<=j) 458 { 459 swap(a[i].x,a[j].x); 460 swap(a[i].y,a[j].y); 461 i++; j--; 462 } 463 } 464 if (l<j) xsort(l,j); 465 if (i<r) xsort(i,r); 466 } 467 void ysort(int l,int r) 468 { 469 int i=l,j=r; 470 int mid=(l+r)/2; 471 while(i<j) 472 { 473 while((a[i].y<a[mid].y)||((a[i].y==a[mid].y)&&(a[i].x<a[mid].x))) 474 i++; 475 while((a[j].y>a[mid].y)||((a[j].y==a[mid].y)&&(a[j].x>a[mid].x))) 476 j--; 477 if (i<=j) 478 { 479 swap(a[i].x,a[j].x); 480 swap(a[i].y,a[j].y); 481 i++; j--; 482 } 483 } 484 if (l<j) ysort(l,j); 485 if (i<r) ysort(i,r); 486 } 487 488 bool cross(point a, point b, point c) { 489 //if ( ((a.y > c.y && b.y <= c.y) || (a.y <= c.y && b.y > c.y)) && c.x < a.x) { 490 if ( ( ( (dblcmp(a.y-c.y)==1) && (dblcmp(b.y-c.y)!=1) )||( (dblcmp(a.y-c.y)!=1) && (dblcmp(b.y-c.y)==1) ) ) && (dblcmp(c.x-a.x)==-1) ) { 491 return true; 492 } 493 return false; 494 } 495 496 int main() 497 { 498 while(cin>>k) 499 { 500 for (int i=1;i<=k;i++) 501 cin>>a[i].x>>a[i].y; 502 503 xsort(1,k); 504 int NL=0; 505 for (int i=1;i<=k-1;i=i+2) 506 { 507 NL++; 508 Line[NL]=line(point(a[i].x,a[i].y),point(a[i+1].x,a[i+1].y)); 509 //cout<<a[i].x<<","<<a[i].y<<" "<<a[i+1].x<<","<<a[i+1].y<<endl; 510 } 511 ysort(1,k); 512 for (int i=1;i<=k-1;i=i+2) 513 { 514 NL++; 515 Line[NL]=line(point(a[i].x,a[i].y),point(a[i+1].x,a[i+1].y)); 516 //cout<<a[i].x<<","<<a[i].y<<" "<<a[i+1].x<<","<<a[i+1].y<<endl; 517 } 518 519 cin>>X0>>Y0; 520 point des=point(X0,Y0); 521 int ans=99,cnt=0; 522 for (int i=1;i<=NL;i++) 523 { 524 line tl=Line[i]; 525 if (tl.pointonseg(des)) 526 { 527 //cout<<i<<endl; 528 ans=2; 529 } 530 if (cross(tl.a,tl.b,des)) 531 { 532 cout<<i<<endl; 533 cnt++; 534 } 535 } 536 if (ans==2) 537 cout<<"BORDER"<<endl; 538 else 539 { 540 if(cnt%2==0) 541 cout<<"OUTSIDE"<<endl; 542 else 543 cout<<"INSIDE"<<endl; 544 } 545 546 /* 547 PY.n=k; PY.nl=NL; 548 for (int i=0;i<k;i++) 549 { 550 cout<<a[i+1].x<<","<<a[i+1].y<<endl; 551 PY.p[i]=point(a[i+1].x,a[i+1].y); 552 } 553 for (int i=0;i<NL;i++) 554 { 555 cout<<Line[i+1].a.x<<","<<Line[i+1].a.y<<"->"<<Line[i+1].b.x<<","<<Line[i+1].b.y<<endl; 556 PY.l[i]=Line[i+1]; 557 } 558 559 cin>>X0>>Y0; 560 int ans=PY.relationpoint(point(X0,Y0)); 561 //3 点上 562 //2 边上 563 //1 内部 564 //0 外部 565 if (ans==1) 566 cout<<"INSIDE"<<endl; 567 else if (ans==0) 568 cout<<"OUTSIDE"<<endl; 569 else 570 cout<<"BORDER"<<endl; 571 */ 572 } 573 return 0; 574 }
时间: 2024-10-06 18:38:50