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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章