BZOJ_1132_[POI2008]Tro_计算几何

BZOJ_1132_[POI2008]Tro_计算几何

Description

平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和 N<=3000

Input

第一行给出数字N,N在[3,3000] 下面N行给出N个点的坐标,其值在[0,10000]

Output

保留一位小数,误差不超过0.1

Sample Input

5
0 0
1 2
0 2
1 0
1 1

Sample Output

7.0

把面积转换成叉积的形式,也就是说我们要求$sumlimits_{i=1}^{n}sumlimits_{j=i+1}^{n}sumlimits_{k=j+1}^{n}|(y_i-y_j)*(x_k-x_i)-(y_k-y_i)*(x_j-x_i)|$
然后枚举i,以第i个点为原点对其他那些点进行极角排序,维护一个前缀和把绝对值化掉,统计那些是加哪些是减即可。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long f2;
#define eps 1e-7
#define N 3050
struct Point {
    f2 x,y;
    Point() {}
    Point(f2 x_,f2 y_) :
        x(x_),y(y_) {}
    Point operator + (const Point &p) const {return Point(x+p.x,y+p.y);}
    Point operator - (const Point &p) const {return Point(x-p.x,y-p.y);}
    bool operator < (const Point &p) const {
        if(y==p.y) return x<p.x; return y<p.y;
    }
}a[N],t[N];
typedef Point Vector;
int n;
f2 sx[N],sy[N];
f2 cross(const Point &p1,const Point &p2) {return p1.x*p2.y-p1.y*p2.x;}
bool cmp(const Vector &x,const Vector &y) {
    return cross(x,y)>eps;
}
int main() {
    scanf("%d",&n);
    int i,j;
    for(i=1;i<=n;i++) {
        scanf("%lld%lld",&a[i].x,&a[i].y);
    }
    sort(a+1,a+n+1);
    f2 ans=0;
    for(i=1;i<=n-2;i++) {
        for(j=i+1;j<=n;j++) t[j]=a[j]-a[i];
        sort(t+i+1,t+n+1,cmp);
        sx[i]=sy[i]=0;
        for(j=i+1;j<=n;j++) {
            sx[j]=sx[j-1]+t[j].x;
            sy[j]=sy[j-1]+t[j].y;
        }
        for(j=i+1;j<=n;j++) {
            ans+=(t[j].x*(sy[n]-sy[j])-t[j].y*(sx[n]-sx[j]));
        }
    }
    printf("%lld.%lld
",ans/2,ans%2*5);
}
原文地址:https://www.cnblogs.com/suika/p/9063062.html