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.
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).
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).
10 4 3 0 0 0
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; }