问题可以这样求解:对于每个点求出它在多少个三角形之中,把这些数做和,就是所有三角形包含点的总数,除以三角形数就是答案。
问题就是对于每个点如何求出它在多少个三角形之中。
设该点为k,反向求有多少个三角形不包含它。方法是把其余点关于这个点k做极角排序,依次枚举每一个点i,把它当作三角形的一点,假设点j是最后一个和点i的夹角在pi以内的,那么在i+1和j之间这些点中任选2个点和i组成三角形,都不包括k。在枚举i时,求点j位置可以根据前一个i递推,也就是把前一次的点数减1,再继续往下边加边判断。时间复杂度是O(n),总体就是O(n^2)。
极角排序用atan2(y,x)函数就可以了,对这个向量返回到x轴正方向的夹角。对精度有损失,追求精度可以用象限+叉积排序。
代码:
//
// main.cpp
// 11529 Strange Tax Calculation
//
// Created by Baoli1100 on 15/2/15.
// Copyright (c) 2015年 Baoli1100. All rights reserved.
//
#include <iostream>
using namespace std;
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define pi acos(-1.0)
#define LL long long
double k[2410];
int N;
double x[1210];
double y[1210];
LL solve(int n){
int cnt=0;
for(int i=0;i<N;i++){
if(i==n) continue;
k[cnt++]=atan2(y[i]-y[n],x[i]-x[n]);
k[cnt++]=atan2(y[i]-y[n],x[i]-x[n])+2*pi;
}
sort(k,k+cnt);
LL res=0;
int pos=0;
LL num=1;
for(int i=0;i<N-1;i++){
num--;
while(k[pos]<k[i]+pi){
num++;
pos++;
}
res+=(num-1)*(num-2)/2;
//cout<<(num-1)*(num-2)/2<<endl;
}
LL tot=(N-1)*(N-2)*(N-3)/6;
return tot-res;
}
int main(){
int kase=1;
while(~scanf("%d",&N)){
if(N==0) break;
for(int i=0;i<N;i++){
scanf("%lf%lf",&x[i],&y[i]);
}
LL tot=0;
for(int i=0;i<N;i++){
tot+=solve(i);
}
double res=tot*1.0/(N*(N-1)*(N-2)/6);
printf("City %d: %.2f\n",kase++,res);
}
return 0;
}
UVa 11529 Strange Tax Calculation(极角排序)