把点按纵坐标排序,依次枚举,把它作为原点,然后把之后的点极角排序,把叉积的公式稍微化简一下,处理个后缀和统计答案。
#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; }