HDU1392

来源:互联网 发布:在职研软件工程硕士 编辑:程序博客网 时间:2024/06/07 13:40

基础的计算几何题,求一个周长最小的,覆盖所有点集的多边形。明显是求凸包。求凸包先要做极角排序,这里不要用斜率做,否则会带来很多麻烦。用叉乘法,分别将两点,B,C与最低点A连接,若AB×AC<0,则B的极角大于C。这里说一下等于0的情况,也就是A,B,C共线,则令离A远的点极角大。然后就是入栈搜索,这一段略。最后,就是求多边形周长。特别的,若入栈使没有拐弯过,即所有点共线,要除2。

一下是程序:

#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

int n;  

struct point
{
       int x;
       int y;
       point()
       {
              x=0;y=0;
       }
      
};

int check(point a,point b,point c)
{
     int x1,x2,y1,y2,r;
     x1=b.x-a.x;
     x2=c.x-a.x;
     y1=b.y-a.y;
     y2=c.y-a.y;
     r=x1*y2-x2*y1;
     return r;
}

double dis(point a,point b)
{
       double r;
       r=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
       r=sqrt(r);
       return r;
}

void anglesort(point* a)
{
     int i,j,r,flag;
     for (i=1;i<n-1;i++)
         for (j=i+1;j<n;j++)
         {
             flag=0;
             r=check(a[0],a[i],a[j]);
             if (r<0) flag=1;
             else if (r==0)
             {
                  if (dis(a[0],a[i])>dis(a[0],a[j])) flag=1;
             }
             if (flag)
             {
                      point tmp=a[i];
                      a[i]=a[j];
                      a[j]=tmp;
             }
         }
}

void input(point* a)
{
      int mi,i,mmin=10e8;
      for (i=0;i<n;i++)
      {
          scanf("%d%d",&a[i].x,&a[i].y);
          if (a[i].y<mmin)
          {
                           mmin=a[i].y;
                           mi=i;
          }
      }
      point tmp=a[mi];
      a[mi]=a[0];
      a[0]=tmp;
      a[n]=a[0];
}

void making(point* a,int* b,double &r)
{
     b[0]=0;b[1]=1;
     int top=1,s=2,t,i,flag=1;
     while (true)
     {
           int x=b[top-1],y=b[top];
           t=check(a[x],a[y],a[s]);
           if (t>=0)
           {
                    if (t!=0) flag=0;
                    b[++top]=s;
                    s++;
           }
           else top--;
           if (b[top]==n) break;
     }
     for (i=0;i<top;i++)
         r+=dis(a[b[i]],a[b[i+1]]);
     if (flag) r/=2.0;
}

int main()
{
    int i,j;
    double r;
    while (scanf("%d",&n))
    {
          r=0;
          if (n==0) break;
          point* a=new point[n+10];
          input(a);
          if (n==2) r=dis(a[0],a[1]);
          else
          {
               r=0;
               anglesort(a);  
               int* b=new int[n+10];
               memset(b,0,sizeof(b));
               making(a,b,r);
               delete []b;
          }
          cout<<fixed<<setprecision(2)<<r<<endl;
          delete []a;
    }
    return 0;
}

 

 

原创粉丝点击