题意:没看懂= =
sol:在纸上随便画两下就可以看出,答案即按逆时针方向建立line,求它们的半平面交的面积。
模板题。注意输出答案时输出ans+eps,否则可能会出现结果为-0.00的情况。
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-6; 32 const double pi=acos(-1.0); 33 const double inf=1e20; 34 const int maxp=1111; 35 int dblcmp(double d) 36 { 37 if (fabs(d)<eps)return 0; 38 return d>eps?1:-1; 39 } 40 inline double sqr(double x){return x*x;} 41 struct point 42 { 43 double x,y; 44 point(){} 45 point(double _x,double _y): 46 x(_x),y(_y){}; 47 void input() 48 { 49 scanf("%lf%lf",&x,&y); 50 } 51 void output() 52 { 53 printf("%.2f %.2f\n",x,y); 54 } 55 bool operator==(point a)const 56 { 57 return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0; 58 } 59 bool operator<(point a)const 60 { 61 return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x; 62 } 63 double len() 64 { 65 return hypot(x,y); 66 } 67 double len2() 68 { 69 return x*x+y*y; 70 } 71 double distance(point p) 72 { 73 return hypot(x-p.x,y-p.y); 74 } 75 point add(point p) 76 { 77 return point(x+p.x,y+p.y); 78 } 79 point sub(point p) 80 { 81 return point(x-p.x,y-p.y); 82 } 83 point mul(double b) 84 { 85 return point(x*b,y*b); 86 } 87 point div(double b) 88 { 89 return point(x/b,y/b); 90 } 91 double dot(point p) 92 { 93 return x*p.x+y*p.y; 94 } 95 double det(point p) 96 { 97 return x*p.y-y*p.x; 98 } 99 double rad(point a,point b) 100 { 101 point p=*this; 102 return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p)))); 103 } 104 point trunc(double r) 105 { 106 double l=len(); 107 if (!dblcmp(l))return *this; 108 r/=l; 109 return point(x*r,y*r); 110 } 111 point rotleft() 112 { 113 return point(-y,x); 114 } 115 point rotright() 116 { 117 return point(y,-x); 118 } 119 point rotate(point p,double angle)//绕点p逆时针旋转angle角度 120 { 121 point v=this->sub(p); 122 double c=cos(angle),s=sin(angle); 123 return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); 124 } 125 }; 126 struct line 127 { 128 point a,b; 129 line(){} 130 line(point _a,point _b) 131 { 132 a=_a; 133 b=_b; 134 } 135 bool operator==(line v) 136 { 137 return (a==v.a)&&(b==v.b); 138 } 139 //倾斜角angle 140 line(point p,double angle) 141 { 142 a=p; 143 if (dblcmp(angle-pi/2)==0) 144 { 145 b=a.add(point(0,1)); 146 } 147 else 148 { 149 b=a.add(point(1,tan(angle))); 150 } 151 } 152 //ax+by+c=0 153 line(double _a,double _b,double _c) 154 { 155 if (dblcmp(_a)==0) 156 { 157 a=point(0,-_c/_b); 158 b=point(1,-_c/_b); 159 } 160 else if (dblcmp(_b)==0) 161 { 162 a=point(-_c/_a,0); 163 b=point(-_c/_a,1); 164 } 165 else 166 { 167 a=point(0,-_c/_b); 168 b=point(1,(-_c-_a)/_b); 169 } 170 } 171 void input() 172 { 173 a.input(); 174 b.input(); 175 } 176 void adjust() 177 { 178 if (b<a)swap(a,b); 179 } 180 double length() 181 { 182 return a.distance(b); 183 } 184 double angle()//直线倾斜角 0<=angle<180 185 { 186 double k=atan2(b.y-a.y,b.x-a.x); 187 if (dblcmp(k)<0)k+=pi; 188 if (dblcmp(k-pi)==0)k-=pi; 189 return k; 190 } 191 //点和线段关系 192 //1 在逆时针 193 //2 在顺时针 194 //3 平行 195 int relation(point p) 196 { 197 int c=dblcmp(p.sub(a).det(b.sub(a))); 198 if (c<0)return 1; 199 if (c>0)return 2; 200 return 3; 201 } 202 bool pointonseg(point p) 203 { 204 return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0; 205 } 206 bool parallel(line v) 207 { 208 return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0; 209 } 210 //2 规范相交 211 //1 非规范相交 212 //0 不相交 213 int segcrossseg(line v) 214 { 215 int d1=dblcmp(b.sub(a).det(v.a.sub(a))); 216 int d2=dblcmp(b.sub(a).det(v.b.sub(a))); 217 int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a))); 218 int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a))); 219 if ((d1^d2)==-2&&(d3^d4)==-2)return 2; 220 return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0|| 221 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0|| 222 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0|| 223 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0); 224 } 225 int linecrossseg(line v)//*this seg v line 226 { 227 int d1=dblcmp(b.sub(a).det(v.a.sub(a))); 228 int d2=dblcmp(b.sub(a).det(v.b.sub(a))); 229 if ((d1^d2)==-2)return 2; 230 return (d1==0||d2==0); 231 } 232 //0 平行 233 //1 重合 234 //2 相交 235 int linecrossline(line v) 236 { 237 if ((*this).parallel(v)) 238 { 239 return v.relation(a)==3; 240 } 241 return 2; 242 } 243 point crosspoint(line v) 244 { 245 double a1=v.b.sub(v.a).det(a.sub(v.a)); 246 double a2=v.b.sub(v.a).det(b.sub(v.a)); 247 return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1)); 248 } 249 double dispointtoline(point p) 250 { 251 return fabs(p.sub(a).det(b.sub(a)))/length(); 252 } 253 double dispointtoseg(point p) 254 { 255 if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0) 256 { 257 return min(p.distance(a),p.distance(b)); 258 } 259 return dispointtoline(p); 260 } 261 point lineprog(point p) 262 { 263 return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2())); 264 } 265 point symmetrypoint(point p) 266 { 267 point q=lineprog(p); 268 return point(2*q.x-p.x,2*q.y-p.y); 269 } 270 }; 271 272 struct Vector:public point 273 { 274 Vector(){} 275 Vector(double a,double b) 276 { 277 x=a; y=b; 278 } 279 Vector(point _a,point _b) //a->b 280 { 281 double dx=_b.x-_a.x; 282 double dy=_b.y-_a.y; 283 x=dx; y=dy; 284 } 285 Vector(line v) 286 { 287 double dx=v.b.x-v.a.x; 288 double dy=v.b.y-v.a.y; 289 x=dx; y=dy; 290 } 291 double length() 292 { 293 return (sqrt(x*x+y*y)); 294 } 295 Vector Normal() 296 { 297 double L=sqrt(x*x+y*y); 298 Vector Vans=Vector(-y/L,x/L); 299 return Vans; 300 } 301 }; 302 303 struct halfplane:public line //半平面 304 { 305 double angle; 306 halfplane(){} 307 //表示向量 a->b逆时针(左侧)的半平面 308 halfplane(point _a,point _b) 309 { 310 a=_a; 311 b=_b; 312 } 313 halfplane(line v) 314 { 315 a=v.a; 316 b=v.b; 317 } 318 void calcangle() 319 { 320 angle=atan2(b.y-a.y,b.x-a.x); 321 } 322 bool operator<(const halfplane &b)const 323 { 324 return angle<b.angle; 325 } 326 }; 327 328 struct polygon 329 { 330 int n; 331 point p[maxp]; 332 line l[maxp]; 333 void input() 334 { 335 n=4; 336 for (int i=0;i<n;i++) 337 { 338 p[i].input(); 339 } 340 } 341 void add(point q) 342 { 343 p[n++]=q; 344 } 345 void getline() 346 { 347 for (int i=0;i<n;i++) 348 { 349 l[i]=line(p[i],p[(i+1)%n]); 350 } 351 } 352 struct cmp 353 { 354 point p; 355 cmp(const point &p0){p=p0;} 356 bool operator()(const point &aa,const point &bb) 357 { 358 point a=aa,b=bb; 359 int d=dblcmp(a.sub(p).det(b.sub(p))); 360 if (d==0) 361 { 362 return dblcmp(a.distance(p)-b.distance(p))<0; 363 } 364 return d>0; 365 } 366 }; 367 void norm() 368 { 369 point mi=p[0]; 370 for (int i=1;i<n;i++)mi=min(mi,p[i]); 371 sort(p,p+n,cmp(mi)); 372 } 373 void getconvex(polygon &convex) 374 { 375 int i,j,k; 376 sort(p,p+n); 377 convex.n=n; 378 for (i=0;i<min(n,2);i++) 379 { 380 convex.p[i]=p[i]; 381 } 382 if (n<=2)return; 383 int &top=convex.n; 384 top=1; 385 for (i=2;i<n;i++) 386 { 387 while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0) 388 top--; 389 convex.p[++top]=p[i]; 390 } 391 int temp=top; 392 convex.p[++top]=p[n-2]; 393 for (i=n-3;i>=0;i--) 394 { 395 while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0) 396 top--; 397 convex.p[++top]=p[i]; 398 } 399 } 400 bool isconvex() 401 { 402 bool s[3]; 403 memset(s,0,sizeof(s)); 404 int i,j,k; 405 for (i=0;i<n;i++) 406 { 407 j=(i+1)%n; 408 k=(j+1)%n; 409 s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1; 410 if (s[0]&&s[2])return 0; 411 } 412 return 1; 413 } 414 //3 点上 415 //2 边上 416 //1 内部 417 //0 外部 418 int relationpoint(point q) 419 { 420 int i,j; 421 for (i=0;i<n;i++) 422 { 423 if (p[i]==q)return 3; 424 } 425 getline(); 426 for (i=0;i<n;i++) 427 { 428 if (l[i].pointonseg(q))return 2; 429 } 430 int cnt=0; 431 for (i=0;i<n;i++) 432 { 433 j=(i+1)%n; 434 int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j]))); 435 int u=dblcmp(p[i].y-q.y); 436 int v=dblcmp(p[j].y-q.y); 437 if (k>0&&u<0&&v>=0)cnt++; 438 if (k<0&&v<0&&u>=0)cnt--; 439 } 440 return cnt!=0; 441 } 442 //1 在多边形内长度为正 443 //2 相交或与边平行 444 //0 无任何交点 445 int relationline(line u) 446 { 447 int i,j,k=0; 448 getline(); 449 for (i=0;i<n;i++) 450 { 451 if (l[i].segcrossseg(u)==2)return 1; 452 if (l[i].segcrossseg(u)==1)k=1; 453 } 454 if (!k)return 0; 455 vector<point>vp; 456 for (i=0;i<n;i++) 457 { 458 if (l[i].segcrossseg(u)) 459 { 460 if (l[i].parallel(u)) 461 { 462 vp.pb(u.a); 463 vp.pb(u.b); 464 vp.pb(l[i].a); 465 vp.pb(l[i].b); 466 continue; 467 } 468 vp.pb(l[i].crosspoint(u)); 469 } 470 } 471 sort(vp.begin(),vp.end()); 472 int sz=vp.size(); 473 for (i=0;i<sz-1;i++) 474 { 475 point mid=vp[i].add(vp[i+1]).div(2); 476 if (relationpoint(mid)==1)return 1; 477 } 478 return 2; 479 } 480 //直线u切割凸多边形左侧 481 //注意直线方向 482 void convexcut(line u,polygon &po) 483 { 484 int i,j,k; 485 int &top=po.n; 486 top=0; 487 for (i=0;i<n;i++) 488 { 489 int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a))); 490 int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a))); 491 if (d1>=0)po.p[top++]=p[i]; 492 if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n])); 493 } 494 } 495 double getcircumference() 496 { 497 double sum=0; 498 int i; 499 for (i=0;i<n;i++) 500 { 501 sum+=p[i].distance(p[(i+1)%n]); 502 } 503 return sum; 504 } 505 double getarea() 506 { 507 double sum=0; 508 int i; 509 for (i=0;i<n;i++) 510 { 511 sum+=p[i].det(p[(i+1)%n]); 512 } 513 return fabs(sum)/2; 514 } 515 bool getdir()//1代表逆时针 0代表顺时针 516 { 517 double sum=0; 518 int i; 519 for (i=0;i<n;i++) 520 { 521 sum+=p[i].det(p[(i+1)%n]); 522 } 523 if (dblcmp(sum)>0)return 1; 524 return 0; 525 } 526 point getbarycentre() 527 { 528 point ret(0,0); 529 double area=0; 530 int i; 531 for (i=1;i<n-1;i++) 532 { 533 double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0])); 534 if (dblcmp(tmp)==0)continue; 535 area+=tmp; 536 ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp; 537 ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp; 538 } 539 if (dblcmp(area))ret=ret.div(area); 540 return ret; 541 } 542 double areaintersection(polygon po) 543 { 544 } 545 double areaunion(polygon po) 546 { 547 return getarea()+po.getarea()-areaintersection(po); 548 } 549 /* 550 double areacircle(circle c) 551 { 552 int i,j,k,l,m; 553 double ans=0; 554 for (i=0;i<n;i++) 555 { 556 int j=(i+1)%n; 557 if (dblcmp(p[j].sub(c.p).det(p[i].sub(c.p)))>=0) 558 { 559 ans+=c.areatriangle(p[i],p[j]); 560 } 561 else 562 { 563 ans-=c.areatriangle(p[i],p[j]); 564 } 565 } 566 return fabs(ans); 567 } 568 //多边形和圆关系 569 //0 一部分在圆外 570 //1 与圆某条边相切 571 //2 完全在圆内 572 int relationcircle(circle c) 573 { 574 getline(); 575 int i,x=2; 576 if (relationpoint(c.p)!=1)return 0; 577 for (i=0;i<n;i++) 578 { 579 if (c.relationseg(l[i])==2)return 0; 580 if (c.relationseg(l[i])==1)x=1; 581 } 582 return x; 583 } 584 void find(int st,point tri[],circle &c) 585 { 586 if (!st) 587 { 588 c=circle(point(0,0),-2); 589 } 590 if (st==1) 591 { 592 c=circle(tri[0],0); 593 } 594 if (st==2) 595 { 596 c=circle(tri[0].add(tri[1]).div(2),tri[0].distance(tri[1])/2.0); 597 } 598 if (st==3) 599 { 600 c=circle(tri[0],tri[1],tri[2]); 601 } 602 } 603 void solve(int cur,int st,point tri[],circle &c) 604 { 605 find(st,tri,c); 606 if (st==3)return; 607 int i; 608 for (i=0;i<cur;i++) 609 { 610 if (dblcmp(p[i].distance(c.p)-c.r)>0) 611 { 612 tri[st]=p[i]; 613 solve(i,st+1,tri,c); 614 } 615 } 616 } 617 circle mincircle()//点集最小圆覆盖 618 { 619 random_shuffle(p,p+n); 620 point tri[4]; 621 circle c; 622 solve(n,0,tri,c); 623 return c; 624 } 625 int circlecover(double r)//单位圆覆盖 626 { 627 int ans=0,i,j; 628 vector<pair<double,int> >v; 629 for (i=0;i<n;i++) 630 { 631 v.clear(); 632 for (j=0;j<n;j++)if (i!=j) 633 { 634 point q=p[i].sub(p[j]); 635 double d=q.len(); 636 if (dblcmp(d-2*r)<=0) 637 { 638 double arg=atan2(q.y,q.x); 639 if (dblcmp(arg)<0)arg+=2*pi; 640 double t=acos(d/(2*r)); 641 v.push_back(make_pair(arg-t+2*pi,-1)); 642 v.push_back(make_pair(arg+t+2*pi,1)); 643 } 644 } 645 sort(v.begin(),v.end()); 646 int cur=0; 647 for (j=0;j<v.size();j++) 648 { 649 if (v[j].second==-1)++cur; 650 else --cur; 651 ans=max(ans,cur); 652 } 653 } 654 return ans+1; 655 } 656 */ 657 int pointinpolygon(point q)//点在凸多边形内部的判定 658 { 659 if (getdir())reverse(p,p+n); 660 if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0) 661 { 662 if (line(p[n-1],p[0]).pointonseg(q))return n-1; 663 return -1; 664 } 665 int low=1,high=n-2,mid; 666 while (low<=high) 667 { 668 mid=(low+high)>>1; 669 if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0) 670 { 671 polygon c; 672 c.p[0]=p[mid]; 673 c.p[1]=p[mid+1]; 674 c.p[2]=p[0]; 675 c.n=3; 676 if (c.relationpoint(q))return mid; 677 return -1; 678 } 679 if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0) 680 { 681 low=mid+1; 682 } 683 else 684 { 685 high=mid-1; 686 } 687 } 688 return -1; 689 } 690 }; 691 692 struct halfplanes //半平面交 693 { 694 int n; 695 halfplane hp[maxp]; 696 point p[maxp]; 697 int que[maxp]; 698 int st,ed; 699 void push(halfplane tmp) 700 { 701 hp[n++]=tmp; 702 } 703 void unique() 704 { 705 int m=1,i; 706 for (i=1;i<n;i++) 707 { 708 if (dblcmp(hp[i].angle-hp[i-1].angle))hp[m++]=hp[i]; 709 else if (dblcmp(hp[m-1].b.sub(hp[m-1].a).det(hp[i].a.sub(hp[m-1].a))>0))hp[m-1]=hp[i]; 710 } 711 n=m; 712 } 713 bool halfplaneinsert() 714 { 715 int i; 716 for (i=0;i<n;i++)hp[i].calcangle(); 717 sort(hp,hp+n); 718 unique(); 719 que[st=0]=0; 720 que[ed=1]=1; 721 p[1]=hp[0].crosspoint(hp[1]); 722 for (i=2;i<n;i++) 723 { 724 while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[ed].sub(hp[i].a))))<0)ed--; 725 while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[st+1].sub(hp[i].a))))<0)st++; 726 que[++ed]=i; 727 if (hp[i].parallel(hp[que[ed-1]]))return false; 728 p[ed]=hp[i].crosspoint(hp[que[ed-1]]); 729 } 730 while (st<ed&&dblcmp(hp[que[st]].b.sub(hp[que[st]].a).det(p[ed].sub(hp[que[st]].a)))<0)ed--; 731 while (st<ed&&dblcmp(hp[que[ed]].b.sub(hp[que[ed]].a).det(p[st+1].sub(hp[que[ed]].a)))<0)st++; 732 if (st+1>=ed)return false; 733 return true; 734 } 735 void getconvex(polygon &con) 736 { 737 p[st]=hp[que[st]].crosspoint(hp[que[ed]]); 738 con.n=ed-st+1; 739 int j=st,i=0; 740 for (;j<=ed;i++,j++) 741 { 742 con.p[i]=p[j]; 743 } 744 } 745 }; 746 747 point p[2000]; 748 halfplanes TH; 749 int n,T; 750 751 int main() 752 { 753 //freopen("in.txt","r",stdin); 754 755 cin>>T; 756 while (T--) 757 { 758 cin>>n; 759 for (int i=n-1;i>=0;i--) 760 p[i].input(); 761 //p[i]->p[i+1] 762 763 TH.n=0; 764 for (int i=0;i<=n-1;i++) 765 TH.push(halfplane(p[i],p[(i+1)%n])); 766 767 double ans=0.00; 768 if (TH.halfplaneinsert()) 769 { 770 polygon Gans; 771 TH.getconvex(Gans); 772 ans=Gans.getarea(); 773 } 774 printf("%.2lf\n",ans+eps); 775 } 776 777 return 0; 778 }
时间: 2024-10-24 15:25:45