简便的方法解决约瑟夫环问题
之前遇到过很多次约瑟夫环的题,一直是在用递归的方法解决,但每次考虑递归的时候都会考虑到发狂,最后终于总结出了一个较为简单的方法
先来叙述一下约瑟夫环的问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。
一开始在编程的时候会有一个惯性思维就是所谓的“退出圈外”,最常想到的就是把这个数从数组中删除,但这样做不仅麻烦并且计算量很大,而换一种思维,就是将退出圈外变为跳过这个数直接记录下一个数。
废话不多说,直接贴代码
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int n,m;
cin>>n>>m;
while(n!=0&&m!=0)
{
int a[n];
for(int i=0;i<n;i++)
{
a[i]=0; //先将数值中的数值全部置零
}
int index=-1; //这里要用负一,否则下面就从一开始了
int count; //定义一个计数器
for(int i=1;i<n;i++)
{
count=0;
while(m!=count) //当计数器数到m时退出循环进行归零
{
index=(index+1)%n;
if(a[index]==0)
{
count++; //如果是零计数器加一,如果是一计数器不计入
if(count==m)
{
a[index]=1; //让第m个数变为一
}
}
}
}
for(int i=0;i<n;i++)
{
if(a[i]==0)
{
cout<<i+1<<endl;
}
}
cin>>n>>m;
}
return 0;
}
总的来说就是保持数组不变,仅仅是跳过不要的数而不是删去,这样可以节约很多资源
当然,这只是我这个菜鸟的一点总结,高手直接略过好了…