Description
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.
Input
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)
Output
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 atrailing comma).
Note:The symbol ⊔ in the Sample Output below represents a space.
Sample Input
8 4 6
10 4 3
10 1 1
10 5 5
0 0 0
Sample Output
⊔⊔4⊔⊔3,⊔⊔8⊔⊔5,⊔⊔7⊔⊔1,⊔⊔6⊔⊔2
⊔⊔4⊔⊔8,⊔⊔9⊔⊔5,⊔⊔3⊔⊔1,⊔⊔6,⊔10,⊔⊔7
⊔⊔1⊔10,⊔⊔2⊔⊔9,⊔⊔3⊔⊔8,⊔⊔4⊔⊔7,⊔⊔5⊔⊔6
⊔⊔5⊔⊔6,⊔⊔1⊔10,⊔⊔8⊔⊔3,⊔⊔9⊔⊔2,⊔⊔4⊔⊔7
解题思路
解题的基本思路是寻找到领取救助金的人,被选中的人将会离开队伍,一种简单的思路就是每次选中后对剩余的人进行重排,但是重排之后,编号就会打乱,可以通过二维数组实现最开始的编号和当前编号的映射(map、指针也可以),但是这样做就有点蛋疼了吧。一维数组的话,只需要每次选中之后,将数组的值置为0,只要每次选取过程中,遇到值为0即不计数,那么实际Coding过程中,按照《算法竞赛入门》的代码打就好了。我的代码仅供参考,可读性比较差,也懒得注释了。
Attention:
1、编号是1~n,不是0开始的
2、不要直接计算选取的人,因为在直接计算的时候会忽略到中间的“空人”
3、每一组数据要换行,不换行的话会WA而不是PE(因为如果上一组最后一个是一个数据,而新的一组也是一个数据,那么不换行就会导致OJ匹配错误)
参考代码
#include<stdio.h>
#include<memory.h>
#define maxn 25
int main()//AC
{
int n,k,m;
while(scanf("%d%d%d",&n,&k,&m)==3&&n){
int peo[maxn],A=0,B=n-1,h=n;
memset(peo,1,maxn*sizeof(int));
while(h!=0){
int m1=m,k1=k;
while(m1--)do{A==0?A=n-1:A--;}while(peo[A]==0);
while(k1--)do{B==n-1?B=0:B++;}while(peo[B]==0);
peo[B]=0;h--;printf("%3d",B+1);
if(B!=A) peo[A]=0,h--,printf("%3d",A+1);
if(h!=0) printf(",");
}
printf("\n");
}
return 0;
}
优化与改进
其实没啥好改进的,while循环那里应该可以优化一下,暂时还没有好的优化想法
UVa链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=69