Wall算法分析与设计

总长度为凸包长度加上以L为半径的圆的周长,n边形的内角和为(n-2)*180,而扇形内角和加上多边形内角和恰为n*180(多边形每个角与对应圆弧的扇形所对应的角互补).

求凸包:

(1)排列:选出纵坐标最小的点,(若存在两点纵坐标相同,则取横坐标小的点)为起点,依次与其他点连接,按极坐标从小道大依次排列(根据叉乘,极坐标小的点在左边.:如线段p1,p2,若p1在p2左边,则(p1.x*p2.y)-(p2.x*p1.y)>0。

(2):连接成凸包:从第一个点开始,找出一个点与之相连,使得该边为该点与所有点连接的边中的最左的边,又从选中的点开始,依次执行之前的过程,直到结束(结束时找到的点为第一个点,围成一个圈)

代码:

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct point{
 int x;
 int y;
}p[1000];
double sum,pI=acos(-1.0)//求出哌的值;
int n,l;
double dis(point p1,point p2){//两点间距离
 double x=p2.x-p1.x;
 double y=p2.y-p1.y;
 return sqrt(x*x+y*y);
}
bool cmp(point p1,point p2){//按极坐标排序
 if((p1.x-p[0].x)*(p2.y-p[0].y)==(p1.y-p[0].y)*(p2.x-p[0].x))
  returnp1.x<p2.x;
 else
  return(p1.x-p[0].x)*(p2.y-p[0].y)>(p1.y-p[0].y)*(p2.x-p[0].x);
}
void search(point q,int a){
 point p3=p[a+1];
 int k,i;
 if(a==n-1)//如果该点已经是最后一个点,则只能与第一个点相连。
  
  sum+=dis(q,p[0]);
 else{
    for(i=a+1;i<n;i++)
     if((p3.x-q.x)*(p[i].y-q.y)-(p3.y-q.y)*(p[i].x-q.x)<=0){找出最左的边,或极坐标一致,但比较长的边
      p3=p[i];
      k=i;
    
           }
       if((p3.x-q.x)*(p[0].y-q.y)-(p3.y-q.y)*(p[0].x-q.x)<=0&&(q.x!=p[0].x))//有可能与第一个点相连
           p3=p[0];
  
  sum+=dis(q,p3);
  if(p3.x!=p[0].x||p3.y!=p[0].y)
           search(p3,k);//如果未围成凸包,则继续查找。
    }
}
int main(){
 point po;
 int i;
   while(scanf("%d%d",&n,&l)!=EOF){
  for(i=0;i<n;i++){
   scanf("%d%d",&p[i].x,&p[i].y);
           if(p[i].y<p[0].y||p[i].y==p[0].y&&p[i].x<p[0].x){//找出第一个点作为起点
               po=p[i];
               p[i]=p[0];
               p[0]=po;
           }

  }
  sort(p+1,p+n,cmp);
  sum=0;
  search(p[0],0);
  double s=2*l*pI;
  sum+=s;
  printf("%d\n",int(sum+0.5));
    }
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值