您的位置:首页 > 其它

UVALive 6859

2016-08-18 18:34 344 查看
凸包模版。

要求将所有点严格包含在内,并且只能走格子的边和对角线。

两种思路:第一种比较好理解,就是将每个点周围四个点,画在图上,去重后套模版,复杂度较高O(4n);其实,将每一个点严格包含在内就是将它旁边的点连接起来,这样同一方向的边与凸包所求出的边是相等的只不过严格包含后需要在结果加上转四个方向时的总长度4 * sqrt(2)就会得到结果。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
struct Point
{
long long x, y;
Point(long long x = 0, long long y = 0) : x(x), y(y) {}
bool operator < (const Point &t) const
{
return x < t.x || x == t.x && y < t.y;
}
bool operator == (const Point &t) const
{
return x == t.x && y == t.y;
}

Point operator - (const Point &t)
{
return Point(x - t.x, y - t.y);
}
}p[100005 * 5], ch[100005 * 5];
long long Cross(const Point &t1, const Point &t2)
{
return t1.x * t2.y - t2.x * t1.y;
}
int ConvexHull()
{
int m = 0;
for(int i = 0; i < n; ++i)
{
while(m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)
--m;
ch[m++] = p[i];
}
int k = m;
for(int i = n - 2; i >= 0; --i)
{
while(m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)
--m;
ch[m++] = p[i];
}
if(n > 1)
--m;
return m;
}
int main()
{
while(~scanf("%d", &n))
{
for(int i = 0; i < n; ++i)
{
scanf("%lld%lld", &p[i].x, &p[i].y);
}
sort(p, p + n);
//        n = unique(p, p + 5 * n) - p;
int m = ConvexHull();
//        double ans = 0;
long long ans1 = 0;
long long ans2 = 0;
ch[m] = ch[0];
for(int i = 0; i < m; ++i)
{
long long d1 = abs(ch[i + 1].x - ch[i].x);
long long d2 = abs(ch[i + 1].y - ch[i].y);
ans1 += max(d1, d2) - min(d1, d2);
ans2 += min(d1, d2);
}
printf("%.6f\n", ans1 + (ans2 + 4) * sqrt(2));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 凸包