Josephus问题

Description

 

 

有1至 N编号的N 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)做游戏。游戏开始时,以正整数m作为报数上限值,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将其密码作为新的报数上限值,从其下一个人开始重新报数,如此下去,直至所有的人全部出列为止。如N=7,m=20,每个人的密码依次是:3172484,则出列顺序为6147235要求最后一个出列的人的编号。

 

Input

 

 

有多组测试数据。每组有两行,第1行有2个正整数nm,(nm<100),n表示人数,m表示开始时报数上限值,第2行有n个整数,一次表示第12…,个人的密码。

 

Output

 

 

对每组测试数据,输出最后一个人的编号。

 

Sample Input

7 20 3 1 7 2 4 8 4

Sample Output

5
 
 
 
#include<iostream>
using namespace std;
void DeleteNum(int num,int *a,int *b);
void Display (int *a);
int main ()
{
	int a[100],b[100];
	int m,n,i;
	while(cin>>n>>m)
{
	for(i=0;i<n;i++)
	{
		a[i]=i+1;
		cin>>b[i];
	}
	b[i]='\0';
	a[i]='\0';
	int length=n;
	int index=m%n;
	while(length!=1)
	{
		if(index==0)
		{
			index=length-1;
		}
		else
		{
			index--;
		}
		m=b[index];
		DeleteNum(index,a,b);
		length--;
		index=m%length;
	}
	cout<<a[index]<<endl;
}

}
void DeleteNum(int num,int *a,int *b)//删除目标,并将删除元素的下一个作为第一个数组元素
{
	int ALength=0;
	for(int i=0;a[i]!='\0';i++)
	{
		ALength++;
	}
	int temp[100];
	int temp2[100];
	int i;
	for (i=0;a[i]!='\0';i++)
	{
		num++;
		if(num>=ALength)
		{
			num-=ALength;
		}
		temp[i]=a[num];
		temp2[i]=b[num];
	}
	temp[i-1]='\0';
	temp2[i-1]='\0';
	int j;
	for(j=0;j<ALength-1;j++)
	{
		a[j]=temp[j];
		b[j]=temp2[j];
	}
	b[j]='\0';	
	a[j]='\0';
	

}
void Display (int  *a)
{
	
	for(int i=0;a[i]!='\0';i++)
		cout<<a[i]<<" ";
		cout<<endl;
}

  大致思路:将每一种情况转化为第一次的情况(即第一个报数的人是数组的第一个元素),这样大大简化了过程。

posted @ 2014-10-06 09:06  你在看孤独的风景  阅读(818)  评论(0编辑  收藏  举报