POJ 1113 Wall

分析:给你n个点的坐标和半径l,求形成的凸包的周长和一个圆的周长和,结果4舍5入。求凸包就用Graham扫描法就好了,以下附两个代码,意思都差不多,要注意的是,double类型的变量存在误差,所以判断是否相等时应该是:a-b<0.000000001 而不是 a==b,做的时候没注意,一直WA。

版本一:

# include <stdio.h>
# include <math.h>
# include <algorithm>
# define PI acos(-1.0)
# define EPS 1e-8
  using namespace std;
  struct point
  {
      double x,y,cos;
  }v[1005];
  double Cross(point a,point b,point c)
  {
      return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
  }
  double Dis(point a,point b)
  {
      return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
  }
  int cmp(point a,point b)
  {
      if(fabs(a.cos-b.cos)>EPS)
        return a.cos>b.cos;
      if(fabs(a.y-b.y)>EPS)
        return a.y<b.y;
      return a.x<b.x;
  }
  int main()
  {
      int i,n,l,min,stack[1005],top;
      double ans,x,y;
      scanf("%d%d",&n,&l);
      for(i=0,min=0;i<n;i++)
      {
          scanf("%lf%lf",&v[i].x,&v[i].y);
          if(v[i].y<v[min].y||(v[i].y==v[min].y&&v[i].x<v[min].x))
            min=i;
      }
      x=v[0].x;y=v[0].y;
      v[0].x=v[min].x;v[0].y=v[min].y;
      v[min].x=x;v[min].y=y;
      for(i=1;i<n;i++)
        v[i].cos=(v[i].x-v[0].x)/Dis(v[i],v[0]);
      sort(v+1,v+n,cmp);
      top=-1;stack[++top]=0;stack[++top]=1;
      for(i=2;i<n;)
      {
          if(Cross(v[stack[top-1]],v[stack[top]],v[i])>=0)
            stack[++top]=i++;
          else
            top--;
      }
      for(i=0,ans=0;i<=top;i++)
        ans+=Dis(v[stack[i]],v[stack[(i+1)%(top+1)]]);
      ans+=2.0*PI*l;
      printf("%d\n",(int)(ans+0.5));
      return 0;
  }



版本二:

# include <stdio.h>
# include <math.h>
# include <algorithm>
# define PI acos(-1.0)
  using namespace std;
  struct point
  {
      int x,y;
  }v[1005];
  int Cross(point a,point b,point c)
  {
      return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
  }
  double Dis(point a,point b)
  {
      return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
  }
  int cmp(point a,point b)
  {
      int t=Cross(v[0],a,b);
      if(t!=0)
        return t>0?1:0;
      return Dis(v[0],a)<Dis(v[0],b);
  }
  void Graham(int n,int l)
  {
      int i,min,top;
      point t,stack[1005];
      double ans;
      for(i=0,min=0;i<n;i++)
        if(v[i].y<v[min].y||(v[i].y==v[min].y&&v[i].x<v[min].x))
          min=i;
      t=v[0]; v[0]=v[min]; v[min]=t;
      sort(v+1,v+n,cmp);
      top=-1; stack[++top]=v[0]; stack[++top]=v[1];
      for(i=2;i<n;i++)
      {
          while(top>0&&Cross(stack[top-1],stack[top],v[i])<=0)
            top--;
          stack[++top]=v[i];
      }
      for(i=0,ans=0;i<=top;i++)
        ans+=Dis(stack[i],stack[(i+1)%(top+1)]);
      printf("%d\n",(int)(ans+2*PI*l+0.5));
  }
  int main()
  {
      int i,n,l;
      scanf("%d%d",&n,&l);
      for(i=0;i<n;i++)
        scanf("%d%d",&v[i].x,&v[i].y);
      Graham(n,l);
      return 0;
  }


你可能感兴趣的:(ACM)