题目链接
逆时针给出 n 个凸多边形的顶点坐标,求它们交的面积。
例如 n=2 时,两个凸多边形如下图:

则相交部分的面积为 5.233。
输入格式
第一行有一个整数 n,表示凸多边形的个数,以下依次描述各个多边形。
第 i 个多边形的第一行包含一个整数 mi,表示多边形的边数,以下 mi 行每行两个整数,逆时针给出各个顶点的坐标。
输出格式
仅包含一个实数,表示相交部分的面积,保留三位小数。
数据范围
2≤n≤10,
3≤mi≤50,
每维坐标为 [−1000,1000] 内的整数。
输入样例:
输出样例:
解题思路
半平面交
先将所有直线极角排序,用栈存储最后保存的直线,对于当前直线,如果其在前两个直线交点的左边,则显然不行,需要出栈,最后要闭合需要判断首尾两条边
代码
// Problem: 凸多边形
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2805/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
//
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=505;
const double eps=1e-8;
typedef pair<double,double> PDD;
int n,m,cnt,q[N];
PDD a[N],ans[N];
struct Line
{
PDD st,en;
}line[N];
PDD operator-(PDD a,PDD b)
{
return {a.fi-b.fi,a.se-b.se};
}
int sign(double x)
{
if(fabs(x)<eps)return 0;
if(x<0)return -1;
return 1;
}
int dcmp(double x,double y)
{
if(fabs(x-y)<eps)return 0;
if(x>y)return 1;
return -1;
}
double cross(PDD a,PDD b)
{
return a.fi*b.se-b.fi*a.se;
}
double area(PDD a,PDD b,PDD c)
{
return cross(b-a,c-a);
}
double get_angle(Line a)
{
return atan2(a.en.se-a.st.se,a.en.fi-a.st.fi);
}
bool cmp(const Line &a,const Line &b)
{
double A=get_angle(a),B=get_angle(b);
if(!dcmp(A,B))return area(a.st,a.en,b.en)<0;
return A<B;
}
PDD get_line_intersection(PDD p,PDD v,PDD q,PDD w)
{
PDD u=p-q;
double t=cross(w,u)/cross(v,w);
return {p.fi+t*v.fi,p.se+t*v.se};
}
PDD get_line_intersection(Line a,Line b)
{
return get_line_intersection(a.st,a.en-a.st,b.st,b.en-b.st);
}
bool on_right(Line a,Line b,Line c)
{
PDD o=get_line_intersection(b,c);
return sign(area(a.st,a.en,o))<=0;
}
double half_plane_intersection()
{
double res=0;
sort(line+1,line+cnt+1,cmp);
int hh=0,tt=-1;
for(int i=1;i<=cnt;i++)
{
if(i>1&&!dcmp(get_angle(line[i]),get_angle(line[i-1])))continue;
while(hh+1<=tt&&on_right(line[i],line[q[tt-1]],line[q[tt]]))tt--;
while(hh+1<=tt&&on_right(line[i],line[q[hh]],line[q[hh+1]]))hh++;
q[++tt]=i;
}
while(hh+1<=tt&&on_right(line[q[hh]],line[q[tt-1]],line[q[tt]]))tt--;
while(hh+1<=tt&&on_right(line[q[tt]],line[q[hh]],line[hh+1]))hh++;
q[++tt]=q[hh];
int k=0;
for(int i=hh;i<tt;i++)ans[++k]=get_line_intersection(line[q[i]],line[q[i+1]]);
for(int i=2;i+1<=k;i++)res+=area(ans[1],ans[i],ans[i+1]);
return res/2;
}
int main()
{
for(scanf("%d",&n);n;n--)
{
scanf("%d",&m);
for(int i=0;i<m;i++)scanf("%lf%lf",&a[i].fi,&a[i].se);
for(int i=0;i<m;i++)line[++cnt]={a[i],a[(i+1)%m]};
}
printf("%.3lf",half_plane_intersection());
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-11-16 华东交通大学2019年ACM 双基 程序设计竞赛
2021-11-16 矩阵乘法