题目描述
小 Z 是一位杰出的数学家。聪明的他特别喜欢研究一些数学小问题。
有一天,他在一张纸上选择了 n 个点,并用铅笔将它们两两连接起来,构成 (�−1)22n(n−1) 条线段。由于铅笔很细,可以认为这些线段的宽度为 。
望着这些线段,小 Z 陷入了冥想中。他认为这些线段中的一部分比较重要,需要进行强调。因此小 Z 拿出了毛笔,将它们重新进行了描边。毛笔画在纸上,会形成一个半径为 �r 的圆。在对一条线段进行描边时,毛笔的中心(即圆心)将从线段的一个端点开始,沿着该线段描向另一个端点。下图即为在一张 44 个点的图中,对其中一条线段进行描边强调后的情况。
现在,小 Z 非常想知道在描边之后纸面上共有多大面积的区域被强调,你能帮助他解答这个问题么?
输入格式
本题是一道提交答案型试题,所有的输入文件 path1.in
∼∼ path10.in
已在相应目录下。
输入文件请点击 这里 下载。
输入文件的第一行为一个正整数 �n,表示选择的点的数目。
第二行至第 �+1n+1 行,其中:第 �+1i+1 行中为两个实数 ��,��xi,yi,表示点 �i 的坐标为 (��,��)(xi,yi)。
第 �+2n+2 行为一个正整数 �m,表示小 Z 认为比较重要的线段的条数。
第 �+3n+3 行至第 �+�+2n+m+2 行,每行有两个正整数 �,�a,b,表示一条线段。其中 �,�a,b 两个数分别表示该线段的两个端点的编号。
第 �+�+3n+m+3 行中为一个实数 �r,表示毛笔在纸上形成的圆的半径。
第 �+�+4n+m+4 行中为四个实数 �1,�2,�3,�4p1,p2,p3,p4,即评分使用的参数。
输出格式
输出文件 path*.out
仅一行一个数,即为描边后被强调区域的总面积。
输入输出样例
输入 #1复制
2
1 1
1 2
1
1 2
1
0.00001 0.001 0.1 1
输出 #1复制
5.1415927
说明/提示
每个测试点单独评分。
本题设有 44 个评分参数 �1,�2,�3,�4p1,p2,p3,p4(�1<�2<�3<�4p1
你的得分将按照如下规则给出:
- 若你的答案与标准答案相差不超过 �1p1,则该测试点你将得到满分;
- 否则,若你的答案与标准答案相差不超过 �2p2,则你将得到该测试点 70%70% 的分数;
- 否则,若你的答案与标准答案相差不超过 �3p3,则你将得到该测试点 40%40% 的分数;
- 否则,若你的答案与标准答案相差不超过 �4p4,则你将得到该测试点 10%10% 的分数;
- 否则,该测试点你的得分为 00。
#include
using namespace std;
typedef long long ll;
typedef long double ld;
const int N=2505;
const ld eps=1e-9;
int n,m,u[N],v[N],cnt;
ld r,mxx=-1e9,mix=1e9,mxy=-1e9,miy=1e9;
ld ans;
struct aa
{
ld x,y;
aa operator +(const aa &b)const{return aa{x+b.x,y+b.y};}
aa operator -(const aa &b)const{return aa{x-b.x,y-b.y};}
aa operator *(const ld &b)const{return aa{x*b,y*b};}
ld operator ^(const aa &b)const{return x*b.y-y*b.x;}
ld operator *(const aa &b)const{return x*b.x+y*b.y;}
ld dis() {return sqrt(x*x+y*y);}
}dt[N];
int sgn(ld x) {return (x>eps)-(x<-eps);}
struct bb
{
ld ps;
int fl;
bool operator <(const bb &b)const{return sgn(ps-b.ps)? psb.fl;}
}Ln[N+N];
bool in(aa s,aa t,aa x)
{
ld lp=((x-s)^(t-s));
if(sgn(lp)>0) swap(s,t);
else lp=-lp;
aa la=t-s,lb=la;
swap(lb.x,lb.y),lb.x=-lb.x;
if(sgn((x-s)^lb)>=0&&sgn((x-t)^lb)<=0) return lp/la.dis()<=r;
return min((x-s).dis(),(x-t).dis())<=r;
}
int main()
{
freopen("path10.in","r",stdin);
freopen("path10.out","w",stdout);
int i,j;
for(cin>>n,i=1;i<=n;i++)
cin>>dt[i].x>>dt[i].y,mxx=max(mxx,dt[i].x),mix=min(mix,dt[i].x),
mxy=max(mxy,dt[i].y),miy=min(miy,dt[i].y);
for(cin>>m,i=1;i<=m;i++) cin>>u[i]>>v[i];
cin>>r,mix-=r,mxx+=r,miy-=r,mxy+=r;
ld px=(mxx-mix)/10000000.0;
int Cl=0;
for(ld X1=mix+px/2,X;X1X&&min(dt[u[i]].x,dt[v[i]].x)-rfabs(dt[v[i]].x-X)) swap(u[i],v[i]);
if(fabs(dt[u[i]].x-X)eps)
{
mid=(pl+pr)/2;
if(in(dt[u[i]],dt[v[i]],aa{X,st+mid})) pl=mid;
else pr=mid;
}
Ln[++cnt]=bb{st+(pl+pr)/2,-1},pl=0,pr=st-miy;
while(pr-pl>eps)
{
mid=(pl+pr)/2;
if(in(dt[u[i]],dt[v[i]],aa{X,st-mid})) pl=mid;
else pr=mid;
}
Ln[++cnt]=bb{st-(pl+pr)/2,1};
}
else
{
if(dt[u[i]].x>dt[v[i]].x) swap(u[i],v[i]);
aa lp=dt[v[i]]-dt[u[i]];
ld la=dt[u[i]].y+lp.y*(X-dt[u[i]].x)/(dt[v[i]].x-dt[u[i]].x),lb=r*lp.dis()/(dt[v[i]].x-dt[u[i]].x);
Ln[++cnt]=bb{la-lb,1},Ln[++cnt]=bb{la+lb,-1};
}
}
sort(Ln+1,Ln+cnt+1);
for(i=1,j=0;i<=cnt;i++)
ans+=(!!j)*(Ln[i].ps-Ln[i-1].ps)*px,j+=Ln[i].fl;
}
printf("%.9Lf",ans);
return 0;
}