连约瑟夫问题的公式都不会,更何况变种了,只好手动模拟
好吧,我确实想到了删除一个数就把它置为0,然后要走的时候再判断...
可是我觉得一旦n变大了,这种方法需要的时间也随之上升,因此手写一个链表来走好了
le[i]代表第i个元素左边的元素的下标,ri[i]代表第i个元素右边元素的下标 ,sz表示链表里还有多少元素。
不过因为我的实现的缘故,依然要把删除的元素置为0,不过我觉得还是比原来的方法要快
删除的时候只要修改左边元素的ri和右边元素的le就好了,以下是代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,k,m,arr[25],be,ed,le[25],ri[25],sz;
int main(){
while(scanf("%d%d%d",&n,&k,&m)==3&&n){
sz=n;
for(int i=0;i<n;++i)
arr[i]=n-i,le[i]=(i-1+n)%n,ri[i]=(i+1)%n;
be=n-1,ed=0;
while(sz){
for(int i=1;i<k;++i)
be=le[be];
for(int i=1;i<m;++i)
ed=ri[ed];
if(sz==1&&be==ed){
printf(" %2d\n",arr[be]);
break;
}
else if(sz==2&&be!=ed){
printf(" %2d %2d\n",arr[be],arr[ed]);
break;
}
else if(be==ed){
printf(" %2d,",arr[be]);
--sz;
arr[be]=0;
ri[le[be]]=ri[be];
le[ri[be]]=le[be];
while(!arr[be])
be=le[be];
while(!arr[ed])
ed=ri[ed];
}
else{
printf(" %2d %2d,",arr[be],arr[ed]);
arr[be]=arr[ed]=0;
sz-=2;
ri[le[be]]=ri[be];
le[ri[be]]=le[be];
ri[le[ed]]=ri[ed];
le[ri[ed]]=le[ed];
while(!arr[be])
be=le[be];
while(!arr[ed])
ed=ri[ed];
}
}
}
return 0;
}