Graham扫描法:参考博客
一开始以为找到一个顶点向右转弯时,把这个顶点抛出只抛出一个,WA了一直找不到bug,用随机数大法测出了一个数据
在这个例子中,走到第4个点时发现向右拐弯了,于是把第4个点抛出,这时第三个点还是向右拐弯的,所以应该一直抛出直到向左拐弯为止。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int mx = 10005;
int n, top;
struct Point {
int x, y;
}pt[mx], stack[mx];
double dis(Point a, Point b) {
return sqrt(1.0*(a.x-b.x)*(a.x-b.x) + 1.0*(a.y-b.y)*(a.y-b.y));
}
int cross(int x1, int y1, int x2, int y2) {
return x1*y2 - x2*y1;
}
bool cmp(Point a, Point b) {
int ans = cross(a.x-pt[1].x, a.y-pt[1].y, b.x-pt[1].x, b.y-pt[1].y);
if (ans != 0) return ans > 0;
else return dis(a, pt[1]) < dis(b, pt[1]);
}
int solve() {
top = 0;
if (n < 3) return .0;
stack[top++] = pt[1];
stack[top++] = pt[2];
stack[top++] = pt[3];
Point a, b, c;
for (int i = 4; i <= n; i++) {
a = stack[top-2]; b = stack[top-1];
int ans = cross(b.x-a.x, b.y-a.y, pt[i].x-a.x, pt[i].y-a.y);
if (ans > 0) stack[top++] = pt[i];
else {
while (ans <= 0) {
top--;
a = stack[top-2]; b = stack[top-1];
ans = cross(b.x-a.x, b.y-a.y, pt[i].x-a.x, pt[i].y-a.y);
}
stack[top++] = pt[i];
}
}
int sum = 0;
for (int i = 2; i < top; i++) {
sum += cross(stack[i-1].x-stack[0].x, stack[i-1].y-stack[0].y, stack[i].x-stack[0].x, stack[i].y-stack[0].y);
}
return sum / 100;
}
int main() {
while (scanf("%d",&n) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%d%d", &pt[i].x, &pt[i].y);
if (pt[i].y < pt[1].y || (pt[i].y == pt[1].y && pt[i].x < pt[1].x)) {
swap(pt[i], pt[1]);
}
}
sort(pt+2, pt+1+n, cmp);
printf("%d\n",solve());
}
return 0;
}