C++经典题目:约瑟夫环问题

问题描述:

有n个人围成一圈,顺序排号。从第一个人开始报数(1~3报数),凡报到3的人退出圈子,问最后留下的人原来排在第几号。

分析:

首先由用户输入人数n,然后对这n个人进行编号【因为如果不编号的话,我们就不能知道最后是哪位童鞋留下来了:)】

然后就开始了一圈一圈的循环,不断形成新的圈子,不断有人被淘汰,那么循环到什么时候截止呢?对只剩最后一个人,也就是说淘汰n-1了个人的时候,这个时候停止循环。

在实际情况中,应该是这n个人一开始围成了一个大圈子,然后随着不断的淘汰,圈子不断减小,最后剩下的那个人的一开始的编号就是我们要的结果。

我在用数组来表示这些人,因为进行了初始化,所以数组中元素的值都是原来的编号,因此我们只需要将被淘汰的人对应的数组元素的值设置为0即可。然后随着不断的循环,最后只剩下一个值不为0的数组元素,这个元素就是我们要的结果。

程序代码

#include<iostream>
using namespace std;
int main()
{
	int i;			//i用来记录数的那个数字 
	int k,j;		//k用来记录淘汰的人数 ,j用来表示第j个人 
 	int Array[10];
 	//对10个人进行编号 
  	for(i=0;i<10;i++)
	{
		Array[i]=i+1;
	}
	i=1;		 
	k=0; 
	/*因为n个人围成一个圈,所以当j>n的时候,j要除n取余,例如(n+1)%n=1
	之所以要++j,而不是j++是因为要先加1再判断*/ 
	for(j=0;k<9;j=++j%10)	 
	{
		if(Array[j]!=0)//当j对应的人没有被淘汰时参与进来,淘汰的直接忽略 
		{
			if(i==3)		//当j对应的人数到m的时候 
			{
				k++;		//淘汰人数加1 
				Array[j]=0;	//对应数组中的数据置为0 
				i=1;		//重新开始报数 
			}
			else
			{
				i++;		//当j对应的人数没有数到m,则进行下一个 
			}
		}
	}
	for(i=0;i<10;i++)
	{
		if(Array[i]!=0)//通过上面的操作,所有淘汰的人员数组对应的值都为0,不为0的就是留下来的 
		{
			cout<<"留下来的是,第"<<i+1<<"个人"<<endl;
		}
	}
	cout<<endl;
	return 0;
}

一些扩展

我们可以对上述程序做一些扩展,让用户输入总人数和用于淘汰的那个数字。

#include<iostream>
using namespace std;
int main()
{
	int i;			//i用来记录数的那个数字 
	int n,m;		
	int k,j;		//k用来记录淘汰的人数 ,j用来表示第j个人 
	cout<<"请输入总人数n和用于淘汰的数字m:";
 	cin>>n>>m;
 	int *Array=new int[n];
 	//对n个人进行编号 
  	for(i=0;i<n;i++)
	{
		Array[i]=i+1;
	}
	i=1;		 
	k=0; 
	/*因为n个人围成一个圈,所以当j>n的时候,j要除n取余,例如(n+1)%n=1
	之所以要++j,而不是j++是因为要先加1再判断*/ 
	for(j=0;k<n-1;j=++j%n)	 
	{
		if(Array[j]!=0)//当j对应的人没有被淘汰时参与进来,淘汰的直接忽略 
		{
			if(i==m)		//当j对应的人数到m的时候 
			{
				k++;		//淘汰人数加1 
				Array[j]=0;	//对应数组中的数据置为0 
				i=1;		//重新开始报数 
			}
			else
			{
				i++;		//当j对应的人数没有数到m,则进行下一个 
			}
		}
	}
	for(i=0;i<n;i++)
	{
		if(Array[i]!=0)//通过上面的操作,所有淘汰的人员数组对应的值都为0,不为0的就是留下来的 
		{
			cout<<"留下来的是,第"<<i+1<<"个人"<<endl;
		}
	}
	cout<<endl;
	return 0;
}

11计信班赵哲

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/qsyzb/article/details/12071123
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞