Josephus问题
Description
有1至 N编号的N 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)做游戏。游戏开始时,以正整数m作为报数上限值,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将其密码作为新的报数上限值,从其下一个人开始重新报数,如此下去,直至所有的人全部出列为止。如N=7,m=20,每个人的密码依次是:3,1,7,2,4,8,4,则出列顺序为6,1,4,7,2,3,5。要求最后一个出列的人的编号。
Input
有多组测试数据。每组有两行,第1行有2个正整数n,m,(n,m<100),n表示人数,m表示开始时报数上限值,第2行有n个整数,一次表示第1,2,…,个人的密码。
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; }
大致思路:将每一种情况转化为第一次的情况(即第一个报数的人是数组的第一个元素),这样大大简化了过程。