【题意】平面上给n个点,问有多少个凸四边形?

【解题方法】对于每个点,凹四边形的个数等于:C(n-1,3)-在这个点同一侧三点构成的三角形的个数。对于凸多边形的一个顶点,

其他顶点必然在穿过这个顶点的直线的同侧。算极角时,如果是负数(-pi ~ 0),就把它加上2 * pi,这样就把角度统一到了0~2pi,另外,向这题顺次统计两个点的夹

角时,由于会出现转了一圈的情况不好计算角度,所以在原来数组后面再顺次加上n-1一个点,角度同一加2pi。

【关键点】极角排序的应用。

【AC  代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn=750;
#define PI acos(-1)
struct Point{
    int x,y;
}p[maxn];
double A[maxn];
int n;
double angle(double x,double y)
{
    double t=y-x;
    if(t<0) t+=2*PI;
    return t;
}
ll solve()
{
    ll ans1=(ll)n*(n-1)*(n-2)*(n-3)/24;
    for(int k=0; k<n; k++)
    {
        int cnt=0;
        for(int i=0; i<n; i++){//计算相对于k点的极角
            if(k!=i) A[cnt++]=atan2((double)(p[i].y-p[k].y),(double)(p[i].x-p[k].x));
        }
        sort(A,A+n-1); //极角排序
        ll ans2=(ll)(n-1)*(n-2)*(n-3)/6;
        for(int j=0,i=0; i<n-1; i++){
            while(j<i+n-1){
                if(angle(A[i],A[j%(n-1)])>PI) break;
                j++;
            }
            ans2-=(j-i-1)*(j-i-2)/2;//减去凸多边形的个数
        }
        ans1-=ans2;//减去凹多边形的个数
    }
    return ans1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++) scanf("%d%d",&p[i].x,&p[i].y);
        ll ans=solve();
        printf("%I64d\n",ans);
    }
}