百练OJ2746: 约瑟夫问题

总时间限制: 
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

  • -------------------------------------------------------------------
  • 1.先开一个长度为300的数组,比如loop[300],然后让loop[i] = i+1,因为位置是从0开始,而要求输出的是编号,从一开始。
  • 2.若一个猴子出圈,假设这个猴子的位置是index,则令loop[index]  = 0 , 这样当进行输出n个猴子的过程如果遇到为0的猴子就意味着它已经出圈了,不用纳入计数。
  • 3.输出n个猴子后要让nPtr回到后一格。nPtr是用来表示当前位置的变量,因为是在一个圆圈中循环,所以每一次前进一格是 nPtr = (nPtr + 1) % total , total是总的猴子数。

#include

int main(){
	int loop[300];
	int total,i,n,nPtr,count;

	while( scanf("%d %d",&total,&n) && total && n ){
		for( i = 0 ; i < total ; i++ )
			loop[i] = i+1;

		nPtr = 0;

		for( i = 0 ; i < total ; i++ ){
			count = 0;
			while( count < n ){
				while( loop[nPtr] == 0 )
					nPtr = (nPtr+1) % total;

				count++;
				nPtr = (nPtr+1) % total;
			}

			nPtr--;
			
                        //nPtr可能为0,这样的话nPtr--可能会让nPtr等于-1,所以如果nPtr等于-1,就让它指向最后一个元素
			if( nPtr < 0 )
				nPtr = total-1;

			if( i == total-1 )
				printf("%d\n",loop[nPtr]);

			loop[nPtr] = 0;
			nPtr = (nPtr+1) % total;
		}		
	}

	return 0;
}


不过这个程序效率不是很高,虽然不会超时,但是逐个跳过为0的元素还是觉得有点傻。可以试试看用链表来储存猴子的顺序,这样的话就省去了判断零的过程了。



你可能感兴趣的:(百练OJ天梯之路)