HDU 1392 Surround the Trees(凸包)

题面

懒得粘贴了。。。
大致题意:坐标系内有若干个点,问把这些点都圈起来的最小凸包周长。

题解

直接求出凸包,统计一遍答案即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
#define MAX 10000
#define INF 1000000000
int n,top;
struct Node
{
       int x,y;
}p[MAX],S[MAX];
inline int read()
{
       int x=0,t=1;char ch=getchar();
       while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
       if(ch=='-'){t=-1;ch=getchar();}
       while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
       return x*t;
}
inline bool cmp(Node a,Node b)
{
       double A=atan2((a.y-p[1].y),(a.x-p[1].x));
       double B=atan2((b.y-p[1].y),(b.x-p[1].x));
       if(A!=B)return A<B;
       else    return a.x<b.x;
}
long long Cross(Node a,Node b,Node c)
{
       return 1LL*(b.x-a.x)*(c.y-a.y)-1LL*(b.y-a.y)*(c.x-a.x);
}
void Get()
{
       p[0]=(Node){INF,INF};int k;
       for(int i=1;i<=n;++i)
              if(p[0].y>p[i].y||(p[0].y==p[i].y&&p[i].x<p[0].x))
               {p[0]=p[i];k=i;}
       swap(p[k],p[1]);
       sort(&p[2],&p[n+1],cmp);
       S[0]=p[1],S[1]=p[2];top=1;
       for(int i=3;i<=n;)
       {
              if(top&&Cross(S[top-1],p[i],S[top])>=0)top--;
              else  S[++top]=p[i++];
       }
}
inline double Dis(Node a,Node b)
{
       return sqrt(1LL*(a.x-b.x)*(a.x-b.x)+1LL*(a.y-b.y)*(a.y-b.y));
}
inline void GetAns()
{
       double Ans=0;
       if(top==0)
          Ans=0;
       else
       if(top==1)
          Ans=Dis(S[0],S[1]);
       else
       {
           S[++top]=S[0];
           for(int i=0;i<top;++i)
             Ans+=Dis(S[i],S[i+1]);
       }
       printf("%.2f\n",Ans);
}
int main()
{
       while(233333)
       {
              n=read();
              if(!n)break;
              for(int i=1;i<=n;++i)
                 p[i]=(Node){read(),read()};
              Get();
              GetAns(); 
       }
       return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值