UVa 11529 Strange Tax Calculation(极角排序)

问题可以这样求解:对于每个点求出它在多少个三角形之中,把这些数做和,就是所有三角形包含点的总数,除以三角形数就是答案。

问题就是对于每个点如何求出它在多少个三角形之中。

设该点为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(极角排序)

你可能感兴趣的:(极角排序)