Bzoj P1069 [SCOI2007]最大土地面積___凸包+旋轉卡殼
阿新 • • 發佈:2018-12-21
題目大意:
在某塊平面土地上有個點,你可以選擇其中的任意四個點,將這片土地圍起來,當然,你希望這四個點圍成 的多邊形面積最大。
分析:
求出凸包, 列舉凸包中對角線, 以對角線為底,求出兩邊的最大面積三角形的面積 然後求一個
程式碼:
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <cmath> #include <cstdlib> #include <algorithm> #define inf 0x3f3f3f3f #define N 2005 using namespace std; struct Node { double x, y; }a[N]; int wxy[N], n, cnt = 0; double Answer; double chaji(int pq, int p, int q) { return (a[p].x - a[pq].x) * (a[q].y - a[pq].y) - (a[q].x - a[pq].x) * (a[p].y - a[pq].y); } double juli(int p, int q) { return sqrt((a[p].x - a[q].x) * (a[p].x - a[q].x) + (a[p].y - a[q].y) * (a[p].y - a[q].y)); } void Get_tb() { double p = inf, q = inf, rp; int useid = 0; for (int i = 1; i <= n; i++) if (p > a[i].x || (p == a[i].x && q > a[i].y)) useid = i, p = a[i].x, q = a[i].y; wxy[++cnt] = useid; int now = 0, orz = 0; while (now != useid) { if (!now) now = useid; for (int i = 1; i <= n; i++) if (i != now) { orz = i; break; } for (int i = 1; i <= n; i++) { rp = chaji(now, orz, i); if (rp < 0 || (rp == 0 && juli(now, i) > juli(now, orz))) orz = i; } wxy[++cnt] = orz; now = orz; } --cnt; } void Get_Answer() { for (int i = 1; i <= cnt; i++) { int id1 = i + 1; if (id1 > cnt) id1 -= cnt; int id2 = i + 3; if (id2 > cnt) id2 -= cnt; for (int j = i + 2; j <= cnt; j++) { while ((fabs(chaji(wxy[i], wxy[j], wxy[id1])) < fabs(chaji(wxy[i], wxy[j], wxy[id1 % cnt + 1]))) && (id1 % cnt + 1 != j)) id1 = id1 % cnt + 1; while ((fabs(chaji(wxy[i], wxy[j], wxy[id2])) < fabs(chaji(wxy[i], wxy[j], wxy[id2 % cnt + 1]))) && (id2 % cnt + 1 != i)) id2 = id2 % cnt + 1; double area = fabs(chaji(wxy[i], wxy[j], wxy[id1])) / 2 + fabs(chaji(wxy[i], wxy[j], wxy[id2])) / 2; if (area > Answer) Answer = area; } } } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lf %lf", &a[i].x, &a[i].y); Get_tb(); Get_Answer(); printf("%.3lf\n", Answer); return 0; }