【计算几何】【极角序】【前缀和】bzoj1132 [POI2008]Tro

把点按纵坐标排序,依次枚举,把它作为原点,然后把之后的点极角排序,把叉积的公式稍微化简一下,处理个后缀和统计答案。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 3002
typedef double db;
typedef long long ll;
struct Point{ll x,y;db jiao;}p[N],v[N];
int n;
ll sumx[N],sumy[N],ans;
bool cmp(const Point &a,const Point &b){return a.y<b.y;}
bool cmp2(const Point &a,const Point &b){return a.jiao<b.jiao;}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	  scanf("%lld%lld",&p[i].x,&p[i].y);
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n-2;++i)
	  {
	  	for(int j=i+1;j<=n;++j)
	  	  {
	  	  	v[j].x=p[j].x-p[i].x;
	  	  	v[j].y=p[j].y-p[i].y;
	  	  	v[j].jiao=atan2((db)v[j].y,(db)v[j].x);
	  	  }
	  	sort(v+i+1,v+n+1,cmp2);
	  	for(int j=n;j>i;--j)
	  	  {
	  	  	sumx[j]=sumx[j+1]+v[j].x;
	  	  	sumy[j]=sumy[j+1]+v[j].y;
	  	  }
	  	for(int j=i+1;j<n;++j)
	  	  ans+=(v[j].x*sumy[j+1]-v[j].y*sumx[j+1]);
	  }
    printf("%lld",ans>>1);
    if(ans&1) puts(".5");
	else puts(".0");
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/4371639.html