题意:略
方法:计算几何?
解析:
看完题以为又要做计算几何了- -!
后来发现我靠不对啊。
这题时限给很长。
但是O(n^3)过不了2333
所以考虑优化。
我们枚举第一个点。
为了使我们不重复枚举三角形。
所以筛出来枚举的第一个点的右面(不包括y负半轴)的点。
然后我们是要计算叉积。
右面的点为了使其有序,所以我们按照斜率排序。
然后枚举到第i个点时,它的贡献是
(y1+y2+…+yi-1)
∗
xi-yi∗(x1+x2+…xi-1)
然后…然后就完事了。
线性记录和即可。
复杂度排序O(nlogn)
所以总的是O(n^2logn)可过。
另外,double的有效数位不够,建议long double 或者特判下奇数即可。
代码:
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define N 3010
using namespace std;
typedef long long ll;
int n;
struct Point
{
int x,y;
Point(){}
Point(int _x,int _y):x(_x),y(_y){}
friend istream& operator >> (istream &_,Point &a)
{
scanf("%d%d",&a.x,&a.y);
return _;
}
Point operator - (const Point &a)
{return Point(x-a.x,y-a.y);}
int operator ^ (Point &a)
{return x*a.y-y*a.x;}
}pt[N],sta[N];
int tot;
bool check (Point &a)
{
if(a.x==0&&a.y>0)return 1;
if(a.x>0&&a.y>0)return 1;
if(a.x>0&&a.y==0)return 1;
if(a.x>0&&a.y<0)return 1;
return 0;
}
bool cmp (Point a,Point b)
{
return (a^b)<0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)cin>>pt[i];
ll sum=0;
for(int i=1;i<=n;i++)
{
tot=0;
for(int j=1;j<=n;j++)
{
if(i==j)continue;
Point tmp=pt[i]-pt[j];
if(check(tmp))
{
sta[++tot]=tmp;
}
}
sort(sta+1,sta+tot+1,cmp);
ll sumx=0,sumy=0;
for(int j=1;j<=tot;j++)
{
sum+=(ll)sta[j].x*sumy-(ll)sta[j].y*sumx;
sumx+=sta[j].x;
sumy+=sta[j].y;
}
}
long double print=(long double)sum/2.0;
cout<<fixed<<setprecision(1)<<print<<endl;
}