[ICPC 2024 Kunming I] 意大利美食题解
题目描述
堡堡为您准备了一份披萨!这个披萨是一个凸多边形,每条饼边里都有芝士夹心。但这些夹心边很脆弱,导致切披萨的时候只能经过多边形的顶点,而不能从边的中间切开。不幸的是,披萨上有一片您肯定不喜欢的,巨大的圆形菠萝片。
求沿着直线切一刀之后,可以获得的最大的没有菠萝的披萨的面积。称一块披萨上没有菠萝,当且仅当菠萝没有任何部分严格位于披萨块内。也就是说,菠萝和披萨的相交面积为 0。
输入格式
有多个测试数据。第一行输入一个整数 T 表示测试数据组数。对于每组测试数据:
第一行输入一个整数 n(3≤n≤105)表示披萨的顶点数。
第二行输入三个整数 xc,yc 和 r(−109≤xc,yc≤109,1≤r≤109)表示菠萝的中心坐标和半径。
对于接下来的 n 行,第 i 行输入两个整数 xi 和 yi(−109≤xi,yi≤109)表示第 i 个顶点的坐标。顶点按逆时针顺序列出。保证任意两点不重合。但可能有三个点在同一直线上。
保证菠萝的任何部分都不会超出披萨的边界。另外保证所有数据 n 之和不超过 105。
输出格式
每组测试数据输出一行一个整数,表示最大的没有菠萝的披萨的面积乘以 2。可以证明这个值始终是一个整数。如果无法切出没有菠萝的披萨块,输出 0。
输入输出样例
输入 #1复制
3 5 1 1 1 0 0 1 0 5 0 3 3 0 5 6 2 4 1 2 0 4 0 6 3 4 6 2 6 0 3 4 3 3 1 3 0 6 3 3 6 0 3
输出 #1复制
5 24 0
说明/提示
样例数据如下图所示。

思路
用向量即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long t,n,x,y,r,rr=0,lk=0,kl=0;
struct one{
long long x,y;
}a[200005];
long long abc2(one xx,one yy,one zz){
return abs((yy.y-xx.y)*(zz.x-xx.x)+(xx.y-zz.y)*(yy.x-xx.x));
}
bool abc3(one s1,one s2,one l1,one l2){
long long t1=(l2.y-l1.y)*(s1.x-l1.x)-(l2.x-l1.x)*(s1.y-l1.y);
long long t2=(l2.y-l1.y)*(s2.x-l1.x)-(l2.x-l1.x)*(s2.y-l1.y);
if((t1>=0&&t2<=0)||(t1<=0&&t2>=0)){
return 1;
}
return 0;
}
bool abc(one xx,one yy,one zz){
__int128 ef,cz,ed;
ef=xx.y-zz.y;
cz=-(xx.x-zz.x);
ed=-cz*xx.y-ef*xx.x;
__int128 dd=(ef*x+cz*y+ed),rr2=r;
if(dd*dd<rr2*rr2*(ef*ef+cz*cz)) return 0;
if(abc3(yy,zz,xx,{x,y})==1) return 0;
else return 1;
}
int main(){
cin>>t;
while(t--){
cin>>n;
cin>>x>>y>>r;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
a[i+n]=a[i];
}
rr=1;
lk=0;
kl=0;
for(int i=1;i<=n;i++){
while(rr+1<=2*n){
if(rr<=i){
rr++;
}
else if(abc(a[i],a[rr],a[rr+1])==1){
lk+=abc2(a[i],a[rr],a[rr+1]);
rr++;
}
else{
break;
}
}
kl=max(kl,lk);
lk-=abc2(a[i],a[i+1],a[rr]);
}
cout<<kl<<endl;
}
return 0;
}

浙公网安备 33010602011771号