POJ 1113 Wall (凸包周长)

来源:互联网 发布:9字网络流行语 编辑:程序博客网 时间:2024/05/16 17:55

http://poj.org/problem?id=1113


使用Graham-Scan算法。

为什么扫描阶段的复杂度是O(n)的?

因为在扫描的过程中,每个点至多进栈一次,至多出栈一次,也就是说对每个点我们至多进行两次叉积运算,所以复杂度是O(n)的。


完整代码:

/*16ms,592KB*/#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const double PI = acos(-1.0);const double eps = 1e-8;const int mx = 1005;struct point{double x, y;point(double x = 0.0, double y = 0.0): x(x), y(y) {}void read() const{scanf("%lf%lf", &x, &y);}bool operator == (const point& a) const{return fabs(x - a.x) < eps && fabs(y - a.y) < eps;}bool operator < (const point& a) const{return x < a.x || fabs(x - a.x) < eps && y < a.y;}};point a[mx], ans[mx];int n, len;inline double dis(point& p1, point& p2){return hypot(p1.x - p2.x, p1.y - p2.y);}///ab x acinline double cross_product(point& a, point& b, point& c){return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);}///求凸包void convex_hull(){sort(a, a + n);//unique(a, a + n);len = 0;int i;///构建一个下凸包,从0到n-1for (i = 0; i < n; ++i){while (len >= 2 && cross_product(ans[len - 2], ans[len - 1], a[i]) < eps)--len;ans[len++] = a[i];}///构建一个上凸包,从n-2到0///注意在构建上凸包的过程中我们用到了n-1这个点///为什么0要算两次?因为我们要借助它来删去那些在凸包内的点int tmp = len;for (i = n - 2; i >= 0; --i){while (len > tmp && cross_product(ans[len - 2], ans[len - 1], a[i]) < eps)--len;ans[len++] = a[i];}--len;///0算了两次}///求凸包周长double perimeter(){double sum = 0.0;ans[len] = ans[0];for (int i = 0; i < len; ++i) sum += dis(ans[i], ans[i + 1]);return sum;}int main(){int l;scanf("%d%d", &n, &l);for (int i = 0; i < n; ++i) a[i].read();convex_hull();printf("%.0f", perimeter() + 2 * l * PI);return 0;}

0 0
原创粉丝点击