从这题中学到了按极角排序后再统计的方法,类似的题有uva11529 Strange Tax Calculation.
由于价格也路程的平方成正比,且要使最短路程同时也价钱最少,故只有锐角三角形符合要求。
我们知道每一个直角或钝角一定是对应一个三角形,这很利于从反面进行统计,(而统计锐角却很棘手,不管什么三角形都存在锐角),然后以该钝角所在顶点A为中心,对其他点按极角排序,枚举另一点B,为使角CAB为钝角或直角,故C所在区域已确定,在该有序的区域统计点数显然非常容易。 因此此问题可在O(n^2*logn)或O(n^2)内解决。
参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int maxn = 1250;
const double pi = acos(-1.0);
const double eps = 1e-10;
struct point{
double x,y;
}p[maxn];
double s[maxn*2];
int main()
{
//freopen("input.txt" , "r" , stdin);
int N , cas = 1;
while(scanf("%d" ,&N)!=EOF && N){
for(int i=0;i<N;i++)
scanf("%lf%lf" , &p[i].x , &p[i].y);
LL obtuse = 0;
for(int i=0;i<N;i++){
if(i) swap(p[i] , p[0]);
for(int k=1;k<N;k++) s[k] = atan2(p[k].y-p[0].y , p[k].x-p[0].x);
sort(s+1 , s+N);
for(int k=1;k<N;k++) s[k+N-1] = s[k] + 2*pi;
int k=1 , e1=1 , e2=1;
for(; k<N; k++){
while(s[e1] - s[k] - 0.5*pi < -eps) e1++;
while(s[e2] - s[k] <= pi) e2++;
obtuse += e2 - e1;
}
}
LL ans = N*(N-1)*(N-2)/6 - obtuse;
printf("Scenario %d:\n" , cas++);
printf("There are %lld sites for making valid tracks\n" , ans);
}
return 0;
}