news 2026/3/4 19:59:44

UVa 137 Polygons

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 137 Polygons

题目描述

题目给出了两个凸多边形,这两个多边形可能重叠,也可能不重叠。如果它们重叠,重叠的程度和方式也会有所不同。要求编写一个程序,读取两个凸多边形的顶点坐标(按顺时针顺序给出),并计算这两个多边形面积的“异或”(exclusive or \texttt{exclusive or}exclusive or)面积,即只属于其中一个多边形所包围的区域面积。所求面积在题目提供的示意图中已用阴影标出。

输入格式

输入由多组数据组成,每组数据包含两行:

  • 第一行:第一个多边形的顶点数n nn,随后是n nn对整数,表示按顺时针顺序的顶点坐标( x , y ) (x, y)(x,y)
  • 第二行:第二个多边形的顶点数m mm,随后是m mm对整数,表示按顺时针顺序的顶点坐标( x , y ) (x, y)(x,y)

所有坐标均为小于100 100100的正整数。输入以一行单独的0 00结束。

输出格式

对于每组数据,输出所求面积,格式为8 88位宽、保留2 22位小数的字段。所有结果在一行内输出,字段间用空格分隔。

样例输入

3 5 5 8 1 2 3 3 5 5 8 1 2 3 4 1 2 1 4 5 4 5 2 6 6 3 8 2 8 1 4 1 4 2 5 3 0

样例输出

␣␣␣␣0.00␣␣␣13.50

(注:样例输出中的空格用⊔ \sqcup表示)


题目分析与解题思路

问题转化

两个多边形A AAB BB的“异或”面积可以表示为:
X O R A r e a = A r e a ( A ) + A r e a ( B ) − 2 × A r e a ( A ∩ B ) XOR_{Area} = Area(A) + Area(B) - 2 \times Area(A \cap B)XORArea=Area(A)+Area(B)2×Area(AB)
其中:

  • A r e a ( A ) Area(A)Area(A)A r e a ( B ) Area(B)Area(B)分别表示两个多边形的面积。
  • A r e a ( A ∩ B ) Area(A \cap B)Area(AB)表示两个多边形的交集面积。

因此,问题的关键在于计算两个凸多边形的交集面积

计算凸多边形交集

两个凸多边形的交集仍然是一个凸多边形(可能为空)。我们可以使用半平面交Half-plane Intersection \texttt{Half-plane Intersection}Half-plane Intersection)的方法来求交集:

  1. 将多边形视为一组半平面

    • 对于凸多边形的每条边,将其视为一个有向线段,方向为多边形顶点的顺时针顺序。
    • 该有向线段左侧(即多边形内部)的区域构成一个半平面。
  2. 构建半平面集合

    • 将多边形A AA的每条边对应的半平面加入集合。
    • 将多边形B BB的每条边对应的半平面加入集合。
  3. 求半平面交

    • 使用排序增量法求所有半平面的交集,得到一个新的凸多边形(交集多边形)。
    • 如果交集为空,则面积为0 00
  4. 计算面积

    • 使用叉积法(Shoelace Formula \texttt{Shoelace Formula}Shoelace Formula)计算多边形面积。

算法步骤

  1. 读取两个多边形的顶点坐标,构建多边形对象。
  2. 分别计算两个多边形的面积。
  3. 构建两个多边形的半平面集合。
  4. 求半平面交,得到交集多边形。
  5. 计算交集多边形面积。
  6. 代入公式计算异或面积并输出。

关键点

  • 由于输入坐标是整数,计算过程中需使用浮点数以保证精度。
  • 注意处理精度误差,例如使用EPSILON = 1 × 10 − 7 \texttt{EPSILON} = 1 \times 10^{-7}EPSILON=1×107进行比较。
  • 输出格式要求8 88位宽、保留2 22位小数,需使用setw(8)setprecision(2)进行控制。

复杂度分析

  • 设两个多边形的总边数为N NN,则半平面交算法的时间复杂度为O ( N log ⁡ N ) O(N \log N)O(NlogN),空间复杂度为O ( N ) O(N)O(N)
  • 由于顶点数不超过100 100100,该算法可以高效运行。

代码实现

// Polygons// UVa ID: 137// Verdict: Accepted// Submission Date: 2017-12-20// UVa Run Time: 0.000s//// 版权所有(C)2016 - 2017,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constintMAXV=1100;constdoubleEPSILON=1E-7;structpoint{doublex,y;point(doublex=0,doubley=0):x(x),y(y){}pointoperator+(point p){returnpoint(x+p.x,y+p.y);};pointoperator-(point p){returnpoint(x-p.x,y-p.y);};pointoperator*(doublek){returnpoint(x*k,y*k);};pointoperator/(doublek){returnpoint(x/k,y/k);};};typedefvector<point>polygon;doublecross(point a,point b){returna.x*b.y-a.y*b.x;}structline{point a,b;doubleangle;};doublecp(point a,point b,point c){returncross(b-a,c-a);}boolcw(point a,point b,point c){returncp(a,b,c)<-EPSILON;}boolcmpLine(line p,line q){if(fabs(p.angle-q.angle)<=EPSILON)returncw(p.a,p.b,q.a);returnp.angle<q.angle;}boolcmpAngle(line p,line q){returnfabs(p.angle-q.angle)<=EPSILON;}boolparallel(line p,line q){returnfabs((p.a.x-p.b.x)*(q.a.y-q.b.y)-(q.a.x-q.b.x)*(p.a.y-p.b.y))<=EPSILON;}pointgetIntersection(line p,line q){point p1=p.a;doublescale=((p.a.x-q.a.x)*(q.a.y-q.b.y)-(p.a.y-q.a.y)*(q.a.x-q.b.x))/((p.a.x-p.b.x)*(q.a.y-q.b.y)-(p.a.y-p.b.y)*(q.a.x-q.b.x));p1.x+=(p.b.x-p.a.x)*scale;p1.y+=(p.b.y-p.a.y)*scale;returnp1;}linepointToLine(point a,point b){line lr;lr.a=a,lr.b=b,lr.angle=atan2(b.y-a.y,b.x-a.x);returnlr;}doublearea(polygon&pg){if(pg.size()<3)return0.0;doubleA=0.0;intn=pg.size();for(inti=0,j=(i+1)%n;i<n;i++,j=(i+1)%n)A+=(pg[i].x*pg[j].y-pg[j].x*pg[i].y);returnfabs(A/2.0);}polygonhalfPlaneIntersection(line*sides,intnLine){polygon pg;line deq[MAXV];sort(sides,sides+nLine,cmpLine);nLine=unique(sides,sides+nLine,cmpAngle)-sides;intbtm=0,top=1;deq[0]=sides[0],deq[1]=sides[1];for(inti=2;i<nLine;i++){if(parallel(deq[top],deq[top-1])||parallel(deq[btm],deq[btm+1]))returnpg;while(btm<top&&cw(sides[i].a,sides[i].b,getIntersection(deq[top],deq[top-1])))top--;while(btm<top&&cw(sides[i].a,sides[i].b,getIntersection(deq[btm],deq[btm+1])))btm++;deq[++top]=sides[i];}while(btm<top&&cw(deq[btm].a,deq[btm].b,getIntersection(deq[top],deq[top-1])))top--;while(btm<top&&cw(deq[top].a,deq[top].b,getIntersection(deq[btm],deq[btm+1])))btm++;if(top<=(btm+1))returnpg;for(inti=btm;i<top;i++)pg.push_back(getIntersection(deq[i],deq[i+1]));if(btm<(top+1))pg.push_back(getIntersection(deq[btm],deq[top]));returnpg;}voidexclusiveOr(polygon&a,polygon&b){doubleareaA=area(a),areaB=area(b);line sides[MAXV];intnLine=0;for(inti=0;i<a.size()-1;i++)sides[nLine++]=pointToLine(a[i+1],a[i]);sides[nLine++]=pointToLine(a[0],a.back());for(inti=0;i<b.size()-1;i++)sides[nLine++]=pointToLine(b[i+1],b[i]);sides[nLine++]=pointToLine(b[0],b.back());polygon c=halfPlaneIntersection(sides,nLine);doublearea1=area(c);doublearea2=areaA+areaB-2*area1;cout<<fixed<<setw(8)<<setfill(' ')<<setprecision(2)<<(area2+1e-9);}intmain(){intn;doublexi,yi;while(cin>>n,n>0){polygon a,b;for(inti=1;i<=n;i++){cin>>xi>>yi;a.push_back(point(xi,yi));}cin>>n;for(inti=1;i<=n;i++){cin>>xi>>yi;b.push_back(point(xi,yi));}exclusiveOr(a,b);}cout<<'\n';return0;}

总结

本题的关键在于将问题转化为求两个凸多边形的交集面积,并利用半平面交算法高效求解。计算几何问题中需特别注意精度处理和边界条件。代码实现中使用了经典的排序增量算法求半平面交,并利用叉积法计算多边形面积,最终通过公式得到异或面积。

该算法在时间和空间上均能满足题目要求,且代码结构清晰,便于理解和调试。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/4 1:11:16

UVa 138 Street Numbers

题目描述 一位计算机程序员住在一条街上&#xff0c;街上的房屋从 111 开始依次编号。每天晚上她遛狗时&#xff0c;都会随机选择向左或向右走&#xff0c;沿着街道一直走到尽头再折返。某天晚上&#xff0c;她计算了途中经过的房屋的街号之和&#xff08;不包括自己家&#xf…

作者头像 李华
网站建设 2026/2/24 1:51:49

springboot校园平台综合服务系统设计实现

校园平台综合服务系统的背景 随着信息化技术的快速发展&#xff0c;高校管理逐渐向数字化、智能化转型。传统校园服务存在信息孤岛、效率低下、资源分散等问题&#xff0c;学生和教职工需要通过多个独立系统完成不同事务&#xff0c;体验较差。SpringBoot作为轻量级Java框架&a…

作者头像 李华