约瑟夫问题(数组解决)

版权声明:@ly https://blog.csdn.net/lytwy123/article/details/83045067

约瑟夫问题:

N个人围成一圈,从第一个人开始报数,数到M得人出圈,再由下一个人开始报数,数到M的人出圈,以此类推,输出除权的编号,N,M由键盘输入。

算法分析:这一道题目用链表做是比较容易的,但是数组也是可以做的并且也比较容易理解,就比如我们知道N个人只有两种状态,出圈和在圈内,那么我们是不是可以定义一个bool类型数组,规定true为出圈,false还在圈内,最初的时候,大家都在圈内,只需要给数组全部初始化为false即可。接下来就是模拟报数出圈的过程,我们首先要把数组看成是一个环状,数组不是连续存储的一片空间地址?怎么变成环,很容易,比如5个人,报数3,一开始是不是报到3有人出圈,那么从3的下一个4开始在报数,那没有6啊,是不是只能4,5,1这样报啊。那么,我们可以设定一个变量去存储报数的位置,当报数的位置超过N个人我们就将报数位置重置为1.接下来就会通过设定的一个计数器记录报数的数字,判断与出圈条件相同即将数组值变为ture,输出记录的报数位置。

代码:

#include<iostream>
using namespace std;
bool num[100];

int main()
{
	int N,M;  //N表示总人数,M代表数到M出局
	cin>>N>>M;
	for(int i = 1;i<=N;i++){
		num[i] = false;    //false代表未出局,ture代表出局 
	} 
	int count = 0; //记录报数的序号
	int location = 0; //记录报数的位置
	int sum = 0; //记录出圈的人数 
	while(sum != N)   //判断所有人是否都出圈了
	{
		location++;   //开始从第一个开始报数
		if(location == N+1) location = 1;   //这个意思是构成一个环状数组,比如你报数报过了N个人是不是又到数组头第一个去报了
		if(num[location] == false) //判断是否出圈了
		count++;
		if(count == M)
		{
			count = 0; //计数器又要从下一个开始报数,置零
			cout<<location<<" ";   //输出出局人数的编号 
			num[location] = true;  //表示出局了
			sum++;   //出局人数记录 
		} 
	} 
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/lytwy123/article/details/83045067