題目
https://vjudge.net/problem/UVA-11529
題意
給出若干個點,保證任意三點不共線,任意選三個點作爲三角行,其他點若又在該三角形內,則算是該三角形內部的點,問所有情況的三角形平均每個三角形有多少個內部點。
思路
三角形的總數很容易求C(3n),現在就是要求各個三角形內部點的總數,同樣我們可以反過來,求每個點在多少個三角形的內部。
然後我們確定一個點,求該點在多少個三角的內部,剩餘n-1個點,可以組成C(3n−1])個三角形,所以只要求出該點在哪些三角形的外部即可。
紅色點爲選中的點,將周圍點按照與選中點的極角進行排序,每次枚舉一點,它的極角爲a,所有極角小於a+pi的點,這些點組成的三角形,選中點一定在外部。處理一週的方式是將點的數組擴大兩倍,將所有點的極角加上pi有保留在延長的數組中。
代碼
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1205;
const double pi = 4 * atan(1.0);
const double eps = 1e-9;
int n;
double s, r[2*N];
struct point {
double x, y;
}p[N];
double Count (int d) {
int c = 0, mv = 0;
for (int i = 0; i < n; i++) {
if (i == d)
continue;
double a = atan2(p[i].y-p[d].y, p[i].x-p[d].x);
r[c] = a;
r[c+n-1] = a + 2*pi;
c++;
}
c = 2 * n - 2;
sort(r, r + c);
double ans = 0;
for (int i = 0; i < n-1; i++) {
double tmp = r[i] + pi;
while (tmp > r[mv])
mv++;
double cnt = mv - i - 1;
ans = ans + cnt * (cnt-1) / 2;
}
return s - ans;
}
double solve () {
s = (n-1) * (n-2) * (n-3) / 6.0;
double c = n * (n-1) * (n-2) / 6.0;
double ans = 0;
for (int i = 0; i < n; i++)
ans += Count(i);
return ans / c;
}
int main () {
int cas = 1;
while (scanf("%d", &n) == 1 && n) {
for (int i = 0; i < n; i++)
scanf("%lf%lf", &p[i].x, &p[i].y);
printf("City %d: %.2lf\n", cas++, solve());
}
return 0;
}