The Dole Queue
The Dole Queue |
In a serious attempt to downsize (reduce) the dole queue, The NewNational Green Labour Rhinoceros Party has decided on the followingstrategy. Every day all dole applicants will be placed in a largecircle, facing inwards. Someone is arbitrarily chosen as number 1,and the rest are numbered counter-clockwise up to N (who will bestanding on 1's left). Starting from 1 and moving counter-clockwise,one labour official counts off k applicants, while another officialstarts from N and moves clockwise, counting m applicants. The two whoare chosen are then sent off for retraining; if both officials pickthe same person she (he) is sent off to become a politician. Eachofficial then starts counting again at the next available person andthe process continues until no-one is left. Note that the two victims(sorry, trainees) leave the ring simultaneously, so it is possible forone official to count a person already selected by the other official.
Input
Write a program that will successively read in (in that order) thethree numbers (N, k and m; k, m > 0, 0 < N < 20) and determinethe order in which the applicants are sent off for retraining. Eachset of three numbers will be on a separate line and the end of datawill be signalled by three zeroes (0 0 0).
Output
For each triplet, output a single line of numbers specifying the orderin which people are chosen. Each number should be in a field of 3characters. For pairs of numbers list the person chosen by thecounter-clockwise official first. Separate successive pairs (orsingletons) by commas (but there should not be a trailing comma).
Sample input
10 4 3 0 0 0
Sample output
4
8,
9
5,
3
1,
2
6,
10,
7
where represents a space.
思路:
也是一道很简单的题,使用环形链表即可。需要注意的地方是一些边界条件,还有就是某个official的所在位置不能是即将被删除的位置。
C++代码实现:
#include <cstdio>
#include <list>
using namespace std;
int main(int argc, char*argv[])
{
int sz;
int k, m, n;
list<int> appl;
list<int>::iterator ccl; // 逆时针迭代器
list<int>::iterator cl; // 顺时针
while (scanf("%d%d%d", &n, &k, &m) != EOF && n && k && m) {
appl.clear();
// 初始化
for (int i = 1; i <= n; ++i) {
appl.push_back(i);
}
ccl = appl.begin();
cl = --appl.end();
while ((sz = appl.size()) > 1) {
for(int i = 1; i < k; ++i) {
if (++ccl == appl.end()) { ccl = appl.begin(); }
}
printf("%3d", *ccl);
for (int i = 1; i < m; ++i) {
if (cl == appl.begin()) { cl = appl.end(); }
--cl;
}
if (cl != ccl) {
printf("%3d", *cl);
// 备份将被删除的节点位置
list<int>::iterator tmp1 = cl;
list<int>::iterator tmp2 = ccl;
do {
if (cl == appl.begin()) { cl = appl.end(); }
--cl;
}while (cl == tmp2); // 不能指向即将被删除的节点
do {
if (++ccl == appl.end()) { ccl = appl.begin(); }
}while (ccl == tmp1); // 不能指向即将被删除的节点
appl.erase(tmp1);
appl.erase(tmp2);
} else {
list<int>::iterator tmp = ccl;
ccl = ++ccl == appl.end() ? appl.begin() : ccl;
cl = cl == appl.begin() ? --appl.end() : --cl;
appl.erase(tmp);
}
if (!appl.empty()) {
printf(",");
}
}
if (!appl.empty()) { printf("%3d", appl.back()); }
printf("\n");
}
return 0;
}