【bzoj1132】[POI2008] Tro

  水题,用来巩固一下叉积。
   cross(u,v)=xuyvxvyu ,其除以2就是 u⃗  v⃗  形成的有向面积。如果保证v在u的下方,则计算其围成的无向面积就不用加绝对值,而且满足结合律。
  先从左往右从下往上枚举点,然后再按以这个点为极点的极角从下往上枚举点,边枚举边算叉积就可以了。
  时间复杂度 O(n2logn)
  采用了机智的方法避免了精度问题。
  

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a,_=b;i<=_;i++)
#define per(i,a,b) for(int i=a,_=b;i>=_;i--)
#define maxn 3003

inline int rd() {
    char c = getchar();
    while (!isdigit(c)) c = getchar() ; int x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x;
}

typedef long long ll;

struct Point {
    int x , y;
    Point(int x = 0 , int y = 0):x(x) , y(y) { }
    friend Point operator-(Point a , Point b) { return Point(a.x - b.x , a.y - b.y) ; }
}t[maxn] , p[maxn];

bool cmp1(const Point a , const Point b) {
    return a.x == b.x ? a.y < b.y : a.x < b.x;
}

bool cmp2(const Point a , const Point b) {
    return (ll) a.y * b.x < (ll) a.x * b.y;
}

int n;

void input() {
    n = rd();
    rep (i , 1 , n) {
        int x = rd() , y = rd();
        p[i] = Point(x , y);
    }
}

void solve() {
    ll ans = 0;
    std::sort(p + 1 , p + n + 1 , cmp1);
    rep (i , 1 , n - 2) {
        ll wx = 0 , wy = 0;
        int l = n - i;
        rep (j , i + 1 , n) t[j - i] = p[j] - p[i];
        std::sort(t + 1 , t + l + 1 , cmp2);
        rep (j , 1 , l) wx += t[j].x , wy += t[j].y;
        rep (j , 1 , l) {
            wx -= t[j].x , wy -= t[j].y;
            ans += (ll) t[j].x * wy - (ll) t[j].y * wx;
        }
    }
    printf("%lld.%d\n" , ans / 2 , (ans & 1 ? 5 : 0));
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.txt" , "r" , stdin);
    #endif
    input();
    solve();
    return 0;
}

你可能感兴趣的:(【bzoj1132】[POI2008] Tro)