The Dole Queue |
In a serious attempt to downsize (reduce) the dole queue, The New National Green Labour Rhinoceros Party has decided on the following strategy. Every day all dole applicants will be placed in a large circle, facing inwards. Someone is arbitrarily chosen as number 1, and the rest are numbered counter-clockwise up to N (who will be standing on 1's left). Starting from 1 and moving counter-clockwise, one labour official counts off k applicants, while another official starts from N and moves clockwise, counting m applicants. The two who are chosen are then sent off for retraining; if both officials pick the same person she (he) is sent off to become a politician. Each official then starts counting again at the next available person and the process continues until no-one is left. Note that the two victims (sorry, trainees) leave the ring simultaneously, so it is possible for one official to count a person already selected by the other official.
Write a program that will successively read in (in that order) the three numbers (N, k and m; k, m > 0, 0 < N < 20) and determine the order in which the applicants are sent off for retraining. Each set of three numbers will be on a separate line and the end of data will be signalled by three zeroes (0 0 0).
For each triplet, output a single line of numbers specifying the order in which people are chosen. Each number should be in a field of 3 characters. For pairs of numbers list the person chosen by the counter-clockwise official first. Separate successive pairs (or singletons) by commas (but there should not be a trailing comma).
10 4 3 0 0 0
4 8, 9 5, 3 1, 2 6, 10, 7
where represents a space.
这道题是一个双向约瑟夫环问题, 我是用数组模拟的,首先用两个数组right1,left1记录结点的左右结点,并且用tag记录这个结点有没有被删掉,模拟的有点烂,不过总算通过了,边界条件要注意。。
#include<iostream> #include<iomanip> #include<cstring> using namespace std; int left1[25],right1[25]; int tag[25]; int main() { int n,k,m; while(cin>>n>>k>>m&&(n||k||m)) { int i,j,len=n,k1=1,m1=n; if(n==1){cout<<" 1"<<endl;continue;} memset(tag,1,sizeof(tag)); memset(left1,0,sizeof(left1)); memset(right1,0,sizeof(right1)); left1[1]=n,right1[1]=2; if(n>1) left1[n]=n-1,right1[n]=1; for(i=2;i<n;i++) { left1[i]=i-1; right1[i]=i+1; } while(len>=1) { for(i=1;i<k;i++) { k1=right1[k1]; } for(i=1;i<m;i++) { m1=left1[m1]; } int l,r; if(m1!=k1&&len>1) { len=len-2; cout<<setw(3)<<k1<<setw(3)<<m1; if(len!=0) cout<<","; l=left1[k1]; r=right1[k1]; right1[l]=r; left1[r]=l; tag[k1]=0; tag[m1]=0; while(!tag[right1[k1]]) { if(len==0) break; k1=right1[k1]; } k1=right1[k1]; l=left1[m1]; r=right1[m1]; right1[l]=r; left1[r]=l; while(!tag[left1[m1]]) { if(len==0) break; m1=left1[m1]; } m1=left1[m1]; } else if(len>1&&m1==k1) { cout<<setw(3)<<m1<<","; len=len-1; l=left1[m1]; r=right1[m1]; right1[l]=r; left1[r]=l; tag[m1]=0; while(!tag[right1[k1]]) { if(len==0) break; k1=right1[k1]; } k1=right1[k1]; while(!tag[left1[m1]]) { if(len==0) break; m1=left1[m1]; } m1=left1[m1]; } else if(len==1&&m1==k1) { cout<<setw(3)<<k1; tag[k1]=0; break; } } cout<<endl; } return 0; }