POJ 1113 Wall

来源:互联网 发布:机械矩阵沙盘排名 编辑:程序博客网 时间:2024/06/06 09:56

分析:给你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;  }


0 0