poj3348(凸包模板题)

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;
}

猜你喜欢

转载自blog.csdn.net/bpdwn2017/article/details/81627794
今日推荐