BZOJ 1132 POI2008 Tro 计算几何

题目大意:给定平面上的一些点,求这些点能组成的所有三角形的面积之和

首先我们枚举每一个点 以这个点为原点建立平面直角坐标系 然后将第一、四象限和x、y轴正半轴上的点按照斜率排序

枚举第二个和第三个点 这样做是O(n^3)的 肯定超时 但是我们发现了什么?

对于每个点k 它对答案的贡献为:

(x1*yk-y1*xk)+(x2*yk-y2*xk)+...+(x_(k-1)*yk-y_(k-1)*xk)

=(x1+x2+...+x_(k-1))*yk-(y1+y2+...+y_(k-1))*xk

于是只要维护一个前缀和即可

时间复杂度O(n^2logn)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 3030
using namespace std;
struct point{
    int x,y;
    double slope;
    point(){}
    point(int _,int __):x(_),y(__)
    {
        slope=x?(double)y/x:1e10;
    }
    bool operator < (const point &Y) const
    {
        if(x!=Y.x)
            return x < Y.x;
        return y < Y.y;
    }
}a[M],points[M];
int n,tot;
long long ans;
bool Compare(const point &p1,const point &p2)
{
    return p1.slope < p2.slope;
}
int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    sort(a+1,a+n+1);
    for(i=1;i<=n;i++)
    {
        tot=0;
        long long sum_x=0,sum_y=0;
        for(j=i+1;j<=n;j++)
            points[++tot]=point(a[j].x-a[i].x,a[j].y-a[i].y);
        sort(points+1,points+tot+1,Compare);
        for(j=1;j<=tot;j++)
        {
            ans+=sum_x*points[j].y-sum_y*points[j].x;
            sum_x+=points[j].x;
            sum_y+=points[j].y;
        }
    }
    printf("%lld.%d\n",ans>>1,ans&1?5:0);
}


你可能感兴趣的:(计算几何,bzoj,BZOJ1132)