poj-约瑟夫问题(猴子选大王)

2746:约瑟夫问题

总时间限制: 
1000ms 
内存限制: 
65536kB
描述
约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。
输入
每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是:

0 0
输出
对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号
样例输入
6 2
12 4
8 3
0 0
样例输出
5
1
7

解题报告:

本题可以用模拟的方法,可以用数组或者是链表解决,用链表的话会更方便些,在这里只介绍下用数组的方法好了,新手比较容易理解。
用houzi[MAX]数组来存放n个数,相当于n个数排成的圈;划掉一个数的操作,就用将一个数组元素置为0的方法来实现。人工数的时候,要跳过已经划掉的数,那么程序执行的时候,就要跳过为0的数组元素。需要注意的是,当 i 指向houzi中最后一个元素(下标n-1)时,要回到第一个元素,这样houzi才像一个圈。
参考程序1:
#include
#define MAX 300
int main()
{
	int houzi[MAX+10],n,m;
	int i;
	int count,sum;		//sum记录猴子总数,count记录当前数到的猴子数

	while(scanf("%d%d",&n,&m)&&(n||m))
	{
	for(i=0;i1)	//当猴子总数超过1时继续操作
	{	count=0;
		while(count=n)
				i%=n;	//下标,当i大于n-1时,回到起点
			if(houzi[i])	//如果猴子未出圈,则数进去
				count++;
			i++;
		
		}
		if(i-1<0)	//注意下标,当数到第n-1只猴子时,下标i会变为0,i-1小于0
			houzi[n-1]=0; //于是第n-1只猴子出圈而不是第i-1只,因为i-1<0
		else
			houzi[i-1]=0;
		sum--;  	//出圈一只,则猴子总数减一


	}
	for(i=0;i

参考程序2:用数组aloop来存放n个数,用变量nptr指向当前数到的数组元素
#include
#define N 300
int main()
{
	int nloop[N+10],nptr,count;
	int n,m,i;
	while(1){
	scanf("%d%d",&n,&m);
	if(n==0)
		break;
	for(i=0;i


你可能感兴趣的:(模拟,poj)