旋转卡壳

看了一些旋转卡壳的资料。理解的还是不深,推荐博客:http://blog.csdn.net/ACMaker

 

POJ 2187

裸凸包+旋转卡(qia)壳,O(n^2)的枚举也能过

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int inf = ~0u>>2;

using namespace std;

const int N = 50010;

int dbcmp(double x) {
    if(x < -eps)    return -1;
    else if(x > eps)    return 1;
    else    return 0;
}

struct point {
    double x;
    double y;
    bool operator < (const point b) const {
        if(dbcmp(y - b.y) == 0) return dbcmp(x - b.x) < 0;
        return dbcmp(y - b.y) < 0;
    }
}p[N], pol[N];

int st[N], n, m, t;
bool vis[N];

double det(double x1, double y1, double x2, double y2) {
    return x1*y2 - x2*y1;
}

double cross(point a, point b, point c) {
    return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
}

double dis2(point a, point b) {
    return (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
}

void Graham(int dir) {
    int i;
    t = 0;
    for(i = 0; i < n; ++i) {
        if(vis[i])  continue;
        while(t > 1 && cross(p[st[t-1]], p[st[t]], p[i])*dir <= 0)   --t;
        st[++t] = i;
    }
    for(i = 2; i < t; ++i)  vis[st[i]] = true;
}

void get_convex_polygons() {
    int i;
    sort(p, p + n);
    CL(vis, false);
    Graham(1);
    m = 0;
    for(i = 1; i <= t; ++i) pol[m++] = p[st[i]];
    Graham(-1);
    for(i = 1; i < t; ++i)  pol[m++] = p[st[t-i]];
}

double roating_calipers() {
    int i, q = 1;
    double ans = 0;
    for(i = 0; i < m - 1; ++i) {
        while(cross(pol[i + 1], pol[q+1], pol[i]) > cross(pol[i + 1], pol[q], pol[i])) {
            q = (q + 1)%m;
        }
        ans = max(ans, max(dis2(pol[i], pol[q]), dis2(pol[i+1], pol[q])));
    }
    return ans;
}

int main() {
    //freopen("data.in", "r", stdin);

    while(~scanf("%d", &n)) {
        for(int i = 0; i < n; ++i) {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        get_convex_polygons();
        printf("%.0f\n", roating_calipers());
    }
    return 0;
}

POJ 2079

用类似选择卡壳的思想。题目让求最大的三角形面积。开始的时候理解成三角形上必须有一个边在凸包上了。O(n^2)枚举边,然后用旋转卡壳的思想确定第3个点。

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int inf = ~0u>>2;

using namespace std;

const int N = 50010;

int dbcmp(double x) {
    if(x < -eps)    return -1;
    else if(x > eps)    return 1;
    else    return 0;
}

struct point {
    double x;
    double y;
    bool operator < (const point b) const {
        if(dbcmp(y - b.y) == 0) return dbcmp(x - b.x) < 0;
        return dbcmp(y - b.y) < 0;
    }
}p[N], pol[N];

int st[N], n, m, t;
bool vis[N];

double det(double x1, double y1, double x2, double y2) {
    return x1*y2 - x2*y1;
}

double cross(point a, point b, point c) {
    return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
}

double dis2(point a, point b) {
    return (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
}

void Graham(int dir) {
    int i;
    t = 0;
    for(i = 0; i < n; ++i) {
        if(vis[i])  continue;
        while(t > 1 && cross(p[st[t-1]], p[st[t]], p[i])*dir <= 0)   --t;
        st[++t] = i;
    }
    for(i = 2; i < t; ++i)  vis[st[i]] = true;
}

void get_convex_polygons() {
    int i;
    sort(p, p + n);
    CL(vis, false);
    Graham(1);
    m = 0;
    for(i = 1; i <= t; ++i) pol[m++] = p[st[i]];
    Graham(-1);
    for(i = 1; i < t; ++i)  pol[m++] = p[st[t-i]];
    /*
    for(i = 0; i < m; ++i) {
        printf("%.0f %.0f\n", pol[i].x, pol[i].y);
    }
    */
}

double roating_calipers() {
    int i, j, q = 1;
    double ans = 0;
    for(i = 0; i < m - 1; ++i) {
        q = 1;
        for(j = i + 1; j < m; ++j) {
            while(cross(pol[j], pol[q+1], pol[i]) > cross(pol[j], pol[q], pol[i])) {
                q = (q + 1)%(m - 1);
            }
            ans = max(ans, fabs(cross(pol[q], pol[i], pol[j])));
        }
    }
    return ans;
}

int main() {
    //freopen("data.in", "r", stdin);

    while(~scanf("%d", &n)) {
        if(n == -1) break;
        for(int i = 0; i < n; ++i) {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        get_convex_polygons();
        printf("%.2f\n", roating_calipers()/2);
    }
    return 0;
}

 

你可能感兴趣的:(旋转卡壳)