您的位置:首页 > 其它

[BZOJ1069][SCOI2007][凸包][旋转卡壳]最大土地面积

2014-05-06 17:02 453 查看
[Problem Description]
在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。
[Algorithm]
凸包 旋转卡壳
[Analysis]
首先选择的这4个点一定在凸包上,所以先求一下凸包。然后枚举四边形的其中一条对角线,然后想办法求出对角线两侧使得四边形面积最大的两个点。假设枚举对角线的时候固定一个点,另一个点顺时针转动,则最优的另外两个点也一定是顺时针转动的。所以边枚举边更新,旋转卡壳的思想。这样的话整个算法的时间复杂度为O(n^2)
[Pay Attention]
注意精度问题和枚举的时候边界问题
[To Myself]
这种几何中的多边形上枚举的题都可以考虑一下旋转卡壳来降低复杂度


[code]/**************************************************************
Problem: 1069
User: gaotianyu1350
Language: C++
Result: Accepted
Time:192 ms
Memory:1316 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const double EPS  = 1e-5;
const int    MAXN = 2100;

inline int dcmp(double a, double b)
{
if (fabs(a - b) < EPS) return 0;
return a > b ? 1 : -1;
}

struct point
{
double x, y;
bool operator < (const point a) const
{
return (!dcmp(x, a.x) && dcmp(y, a.y) < 0) || dcmp(x, a.x) < 0;
}
};

inline double dmax(double a, double b)
{
return a > b ? a : b;
}

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

inline double area(point a, point b, point c)
{
return fabs(cross(a, b, c));
}

point p[MAXN];
int t[MAXN], cnt = 0;
int n;

inline void MakeTubao()
{
sort(p + 1, p + 1 + n);
for (int i = 1; i <= n; i++)
{
while (cnt > 1 && dcmp(cross(p[t[cnt - 1]], p[t[cnt]], p[i]), 0) >= 0)
cnt--;
t[++cnt] = i;
}
int temp = cnt;
for (int i = n - 1; i >= 1; i--)
{
while (cnt > temp && dcmp(cross(p[t[cnt - 1]], p[t[cnt]], p[i]), 0) >= 0)
cnt--;
t[++cnt] = i;
}
if (n > 1) cnt--;
}

inline double Solve(int st)
{
double ans = 0;
t[cnt + 1] = t[1];
int q1 = st, q2 = st + 2;
for (int j = st + 2; j <= cnt; j++)
{
if (st == 1 && j == cnt) continue;
while (dcmp(area(p[t[st]], p[t[j]], p[t[q1 + 1]]),
area(p[t[st]], p[t[j]], p[t[q1]])) >= 0)
q1 = q1 % cnt + 1;
while (dcmp(area(p[t[st]], p[t[j]], p[t[q2 + 1]]),
area(p[t[st]], p[t[j]], p[t[q2]])) >= 0)
q2 = q2 % cnt + 1;
ans = dmax(ans, area(p[t[st]], p[t[j]], p[t[q1]]) + area(p[t[st]], p[t[j]], p[t[q2]]));
}
return ans;
}

int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lf%lf", &p[i].x, &p[i].y);
MakeTubao();
double ans = 0;
for (int i = 1; i <= n - 2; i++)
{
double temp = Solve(i);
ans = dmax(ans, temp);
}
printf("%.3f\n", ans / 2);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息