nyoj 78 圈水池

来源:互联网 发布:苹果6s淘宝下载不了 编辑:程序博客网 时间:2024/04/29 03:24

点击打开题目链接


Andrew's Monotone Chain二维凸包算法详解:点击打开博客链接


Graham的栈扫描转自:http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html



Graham的扫描是一个很优美的过程 用到的数据结构也很简单 仅仅是一个栈而已


核心的思想是按照排好的序 依次加入新点得到新的边


如果和上一条边成左转关系就压栈继续 如果右转就弹栈直到和栈顶两点的边成左转关系 压栈继续


实现的时候我们不用存边 只需要含顺序在栈里存点 相邻两点就是一条边


由于我们时时刻刻都保证栈内是一个凸壳 所以最后扫描完毕 就得到了一个凸包


下面还是继续上面的那个样例 演示一下栈扫描的过程


这样Graham扫描算法基本完成


复杂度是排序O(Nlog2N) 扫描O(N) {每个点仅仅出入栈一次}


合起来是一个O(Nlog2N)的算法 很优秀


实现代码如下:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int INF=110;struct Convex{    int x,y;}Hull[INF],Res[INF];bool cmp(Convex a,Convex b){    return (a.x<b.x)||(a.x==b.x && a.y<b.y);}bool Judge(Convex a,Convex b,Convex c){    return (c.x-a.x)*(c.y-b.y)>(c.y-a.y)*(c.x-b.x);}int ConvexHull(int len){    sort(Hull,Hull+len,cmp);    int m(0);    for(int i=0;i<len;i++)    {        while(m>1 && Judge(Res[m-2],Res[m-1],Hull[i]))            m--;        Res[m++]=Hull[i];    }    int temp=m;    for(int i=len-2;i>=0;i--)    {        while(m>temp && Judge(Res[m-2],Res[m-1],Hull[i]))            m--;        Res[m++]=Hull[i];    }    if(len>1) m--;    return m;}void Print(int len){    sort(Res,Res+len,cmp);    for(int i=0;i<len;i++)        printf("%d %d\n",Res[i].x,Res[i].y);}int main(){    int ncase;    scanf("%d",&ncase);    while(ncase--)    {        int m;        scanf("%d",&m);        for(int i=0;i<m;i++)            scanf("%d%d",&Hull[i].x,&Hull[i].y);        int temp=ConvexHull(m);        Print(temp);    }    return 0;}



原创粉丝点击