使用数组解决约瑟夫环问题

  约瑟夫环是这样: num个小孩围成一圈,从第s个小孩开始数数,数到m时,这个小孩退出.

然后重新从下一个小孩开始.直到只剩下一个为止.
虽然使用循环链表很方便, 但数组一样可以, 只是算法稍微麻烦一点.
struct Boy{

 int num;

 bool isOut;

};
Boy boy[NUM]; 定义一个数组, 用isOut表示是否退出
关键的算法如下
for(int t=0;!isOneBoy();){  //isOneBoy()判断是否只剩下一个
/*
下面的循环最容易出错,我调试好半天才弄明白几个地方
1. 数数时要注意:出列的不算.所以 for循环m次,目的是加上m个还在的小孩
2. 每次重新开始数数时也要注意,把出列的排除,即:isOut为true的不算
*/
  for(int i=0;i<interval-1;i++){
   posiToMove+=1;
   while(boy[posiToMove%size].isOut==true){          //出列的不计数
    posiToMove++;
   }
  }
   boy[posiToMove%size].isOut=true;
   posiToMove+=1;                                         //移到下一个位置, 重新开始数

  while(boy[posiToMove%size].isOut==true){                  //出列的不计数
            posiToMove++;
    }
  posiToMove%=size;
}
以上就是最麻烦的,其他就简单了, 如判断是否只剩下一个小孩:
bool isOneBoy( ){
  bool t=true;
  for(int i=0;i<NUM;i++){
     if(boy[i].isOut==false){
           t=!t;
     }
    if(boy[i].isOut==false&&t==true){
       return false;
    }
  }
 return true;
}
结果: 当10个小孩,开始位置为3, 间隔为3 时, 出列: 5 8 1 4 9 3 10 7 2
最后的剩下的是6
 

发布了11 篇原创文章 · 获赞 5 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/abigriver/article/details/1911921