NC15744. 小白兔小灰兔
描述
老山羊伯伯在地里收白菜,小白兔和小灰兔看见了就一起来帮忙。
他们干了半天,终于干完了。
羊伯伯:小灰兔,这车白菜送给你!
小灰兔:谢谢羊伯伯!
羊伯伯:小白兔,我也送你一车白菜!
小白兔:我不要白菜!给我一包白菜种子吧!
羊伯伯:好!给你~
小白兔:谢谢羊伯伯~
小灰兔把白菜拉到家里之后,就跟大家梦想中的生活一样,躺着啥都不干,吃吃吃,吃了玩~(好想一辈子都这样啊~小灰兔心想。)
小白兔把种子拿回去,打算开始勤劳地种白菜。然而他发现不是所有土地都能用来种白菜,只有被阳光照到的地方可以种白菜。
小白兔生活的星球可以看作二维平面中的一个简单多边形,太阳可以看作一个点。小白兔想知道,这个星球上一共有长度多少的土地可以用来种白菜。
输入描述
第一行是一个正整数T(≤ 20),表示测试数据组数,
对于每组测试数据,
第一行是一个整数n(3≤ n≤ 10),表示简单多边形的顶点数,
接下来n行,每行是两个整数xi,yi(-10≤ xi,yi≤10),按照逆时针绕向给出简单多边形的n个顶点的坐标,
最后一行是两个整数x,y(-10≤ x,y≤10),表示太阳的坐标,保证太阳在多边形外且不在多边形任意一条边所在直线上。
输出描述
对于每组测试数据,输出一行,包含一个实数,表示可以用来种白菜的土地的总长度,要求相对误差不超过,
也就是说,令输出结果为a,标准答案为b,若满足,则输出结果会被认为是正确答案。
示例1
输入:
2 4 0 0 2 0 2 2 0 2 4 1 4 0 0 2 0 2 2 0 2 4 4
输出:
2.000000000000 4.000000000000
C++ 解法, 执行用时: 3ms, 内存消耗: 424K, 提交时间: 2021-10-26 16:58:25
#include<bits/stdc++.h> using namespace std; #define ll long long #define db double const int N=100; const db eps=1e-9,inf=1e18; ll t,n,m; int sign(db k) { return k<-eps? -1: (k>eps? 1: 0); } struct poi { db x,y; poi operator+(const poi& a) const { return poi{x+a.x,y+a.y}; } poi operator-(const poi& a) const { return poi{x-a.x,y-a.y}; } poi operator*(const db& k) const { return poi{x*k,y*k}; } }; db Cro(poi a,poi b) { return a.x*b.y-a.y*b.x; } db Dot(poi a,poi b) { return a.x*b.x+a.y*b.y; } db Len(poi a) { return sqrt(Dot(a,a)); } poi ps[N],s; //返回切点占AB比例,距A比例 db divR(poi a,poi b,poi c,poi d) { poi t1=a-b,t2=c-d,t3=a-c; if(sign(Cro(t1,t2))==0) return -inf; db ret = (Cro(t3,t2)) / (Cro(t1,t2)); return sign(ret)>=0 && sign(ret-1)<=0 ? ret:-inf; } //判线段相交 bool pan_cross_LL(poi a,poi b,poi c,poi d) { db c1=Cro(b-a,c-a),c2=Cro(b-a,d-a); db d1=Cro(d-c,a-c),d2=Cro(d-c,b-c); return sign(c1)*sign(c2)<=0 && sign(d1)*sign(d2)<=0; } int main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>t; while(t--) { cin>>n; for(int i=1;i<=n;i++) cin>>ps[i].x>>ps[i].y; ps[n+1]=ps[1]; cin>>s.x>>s.y; db ans=0; for(int i=1;i<=n;i++) { vector<db> cp; for(int j=1;j<=n;j++) { db ins=divR(ps[i],ps[i+1],s,ps[j]); if(ins>=-1) cp.push_back(ins); } sort(cp.begin(),cp.end()); db rate=0; for(int j=0;j<(int)cp.size()-1;j++) { poi cut=ps[i]+(ps[i+1]-ps[i])*((cp[j]+cp[j+1])/2); bool isok=0; for(int k=1;k<=n;k++) { if(k==i) continue; if(pan_cross_LL(s,cut,ps[k],ps[k+1])) { isok=1;break; } } if(!isok) rate+=cp[j+1]-cp[j]; } ans+=rate*Len(ps[i+1]-ps[i]); } cout<<fixed<<setprecision(12)<<ans<<"\n"; } return 0; }