您的位置:首页 > 其它

zoj 1453 Surround the Trees (求凸包的周长)

2014-08-05 10:47 405 查看
求凸包是按照算法导论上讲的Graham扫描法通过维持一个关于候选点的

栈s来解决的。该算法的复杂度为O(nlogn)。

具体算法建算法导论605面。

我开始写的 极角排序 有点问题,总是搞不清方向= =。。。。

后来改对了。。。

总之这是我第一个凸包啊凸包啊凸包啊O(∩_∩)O哈哈~。。。。。。

so happy~~~~~~~~~~~~

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 110

using namespace std;

struct node
{
    double x,y;
}point[maxn];
node s[maxn];
int top,n;
bool vis[maxn];

bool cmp(node a,node b)
{
    return ((a.y<b.y) || (a.y==b.y && a.x<b.x));
}
bool isTurnLeft(node p1,node p2,node p3)  //p1p3在p1p2左边
{
    double tmp = (p3.x-p1.x)*(p2.y-p1.y)-(p2.x-p1.x)*(p3.y-p1.y);
    if(tmp<0) return true;
    else return false;
}
bool cmp1(node p1,node p2)
{
    return isTurnLeft(point[0],p1,p2);
}
double dis(node a,node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void cal()
{
    double ans = 0;
    for(int i=0;i<top-1;i++)
        ans+=dis(s[i],s[i+1]);
    ans += dis(s[0],s[top-1]);
    printf("%.2lf\n",ans);
}
void solve()
{
    top = 0;
    s[top++] = point[0];
    s[top++] = point[1];
    s[top++] = point[2];
    for(int k=3;k<n;k++)
    {
        while(!isTurnLeft(s[top-2],s[top-1],point[k]))
            --top;
        s[top++] = point[k];
    }
    cal();
}

int main()
{
    while(~scanf("%d",&n) && n)
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&point[i].x,&point[i].y);
        if(n==1)
        {
            printf("0.00\n");
            continue;
        }
        if(n==2)
        {
            printf("%.2lf\n",2*dis(point[0],point[1]));
            continue;
        }
        sort(point,point+n,cmp);
        sort(point+1,point+n,cmp1);
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: