BZOJ 1132 [POI2008]Tro 计算几何

题意:

方法:计算几何?

解析:

看完题以为又要做计算几何了- -!

后来发现我靠不对啊。

这题时限给很长。

但是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;
}

你可能感兴趣的:(poi,X)