水题,用来巩固一下叉积。
cross(u,v)=xuyv−xvyu
,其除以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;
}