凸包

凸包
曾经感觉很可怕的东西如今看了几眼就明白了
先按x为第一关键字,y为第2关键字排序
先跑凸包下半部分
然后逐个放进栈里,当栈中元素的个数大于2的时候,用栈顶元素和前前个点的斜率和栈顶元素和前个点的斜率比较,如果当前点对应的斜率更小,那么就把前一个点踢掉,1到n扫一遍,最后加一波答案
最后再跑凸包上半部分

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<set>
#include<map>
#include<stack>
#include<cstring>
#define inf 21474836.0
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,nl,mid,l,r
#define rson rs,mid+1,nr,l,r
#define N 100010
#define For(i,a,b) for(int i=a;i<=b;i++)
#define p(a) putchar(a)
#define g() getchar()

using namespace std;
struct node{
    double x,y;
}a[10010];

int n;
int top;
node s[10010];
double ans;

void in(int &x){
    int y=1;
    char c=g();x=0;
    while(c<'0'||c>'9'){
        if(c=='-')y=-1;
        c=g();
    }
    while(c<='9'&&c>='0'){
        x=(x<<1)+(x<<3)+c-'0';c=g();
    }
    x*=y;
}
void o(int x){
    if(x<0){
        p('-');
        x=-x;
    }
    if(x>9)o(x/10);
    p(x%10+'0');
}

bool cmp(node x,node y){
    if(x.x==y.x)
        return x.y<y.y;
    return x.x<y.x;
}

double getk(node x,node y){
    if(x.x==y.x)
        return inf;
    return (x.y-y.y)/(x.x-y.x);
}

double dis(node x,node y){
    return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}

int main(){
    in(n);
    For(i,1,n)
        cin>>a[i].x>>a[i].y;
    sort(a+1,a+n+1,cmp);
    For(i,1,n){
        s[++top]=a[i];
        while(top>2&&getk(s[top],s[top-2])<getk(s[top-1],s[top-2])){
            s[top-1]=s[top];
            top--;
        }
    }
    For(i,1,top-1)
        ans+=dis(s[i],s[i+1]);
    top=0;
    for(int i=n;i;i--){
        s[++top]=a[i];
        while(top>2&&getk(s[top],s[top-2])<getk(s[top-1],s[top-2])){
            s[top-1]=s[top];
            top--;
        }
    }
    For(i,1,top-1)
        ans+=dis(s[i],s[i+1]);
    printf("%.2f",ans);
    return 0;
}
View Code

 

posted @ 2019-03-26 21:22  WeiAR  阅读(128)  评论(0编辑  收藏  举报