题目链接 https://cn.vjudge.net/problem/UVA-11529
(复习期末期间日常的小题
想到了考虑每个点被多少个三角形包围,但是没想到怎么算。。。主要还是计算几何太萎le,完全没有想到可以极角排序处理emmm。
具体的就是,考虑每一个点被多少个三角形包含,但是直接考虑也不好计算,可以考虑反向计算出不被多少个三角形包含,这个计算就要用到极角排序了。。。循环遍历每个点,在每个xi点,都对所有的其他点(姑且称为角点吧)相对于这个xi点的极角做一个排序,然后利用三角形的性质,选一个方向(顺时针或者逆时针都行),依次考虑“以每个角点为最小极角与之角度差小于pi的最大角度点之间有多少个点“,可能难以理解,画个图就好了,算出来点的数量p(p包含最大的那个点)之后C(p,2)就是“包含当前最小角点的所有的不覆盖xi点的三角形数量”,依次累加就好了。。。
另外,画个图就会发现,还需要考虑圆周转一圈的情况,所以要把排序后的极角数组复制一遍,而且复制出来的这个数组每个元素还要加2pi!(这个自己试试就知道了)
然后就是找最大点的步骤要小心,很容易写错。。莫名其妙,也可能是我最近复习微机原理复习傻了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1205;
const int mod =1e9+7;
const int INF=0X3f3f3f3f;
const double pi=3.14159265358979323846;
int x[maxn],y[maxn],N;
double alg[maxn<<1];
bool cmp(int a,int b)
{
return alg[a]<alg[b];
}
void asort(int k)
{
for (int i=1,j=1;i<=N;i++)if(i!=k)
{
id[j]=i;
alg[j]=atan2(y[i]-y[k],x[i]-x[k]);
j++;
}
sort(alg+1,alg+N);
for (int i=1;i<=N-1;i++)
alg[i+N-1]=alg[i]+2*pi;
}
LL C3(LL a)
{
if (a<3)
return 0;
else
return a*(a-1)*(a-2)/6;
}
int main()
{
int cs=0;
while(~scanf("%d",&N)&&N)
{
cs++;
for (int i=1;i<=N;i++)
scanf("%d%d",&x[i],&y[i]);
LL ans=0,res,tmp=0,pos;
for (int i=1;i<=N;i++)
{
pos=1,res=1,tmp=0;
asort(i);
for (int j=1;j<=N-1;j++)
{
for(;alg[pos+1]-alg[j]<=pi;pos++,res++);
tmp+=(res>=3?(res-1)*(res-2)/2:0);
res--;
}
ans+=C3(N-1)-tmp;
}
if(N<3)
printf("City %d: 0\n");
else
printf("City %d: %.2f\n",cs,(1.0*ans)/C3(N));
}
return 0;
}
