看了一些旋转卡壳的资料。理解的还是不深,推荐博客:http://blog.csdn.net/ACMaker
POJ 2187
裸凸包+旋转卡(qia)壳,O(n^2)的枚举也能过
//#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个点。
//#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; }