The Dole Queue
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.
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 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.
#include <cstdio>
#include <cstdlib>
struct Person{
struct Person *front;
int value;
struct Person *next;
};
Person *top, *end;
int n, k, m;
int nCase=0;
void solve()
{
if(nCase)printf("\n");
Person *left=top, *right=end;
Person *left_last = left, *right_last=right;
while(1)
{
for(int i=2; i <= k; i++)
{
left_last= left;
left = left->next;
}
for(int j=2; j <= m; j++)
{
right_last = right;
right=right->front;
}
if(left==right)
{
if(n==1){
printf("%3d", left->value);
break;
}else{
printf("%3d,", left->value);
right_last->front = left_last;
left_last->next = right_last;
left = left->next;
right = right->front;
n--;
}
}else{
printf("%3d",left->value);
left_last->next = left->next;
left->next->front = left_last;
printf("%3d",right->value);
right->front->next = right_last;
right_last->front = right->front;
n -=2;
if(n==0) break;
else printf(",");
Person *l=left, *r=right;
l = l->next;
r = r->front;
if(l==right)
l = l->next;
if(r==left)
r = r->front;
left = l;
right = r;
}
}
}
void init()
{
Person *p = (Person *)malloc(sizeof(Person));
Person *pre=NULL;
top = p; pre = p;
p->front = NULL;
p->next=NULL;
p->value = 1;
for(int i=2; i <= n; i++)
{
Person *person = (Person *)malloc(sizeof(Person));
pre->next = person;
person->front = pre;
person->next = NULL;
person->value = i;
pre = pre->next;
}
pre->next = p;
p->front = pre;
end = pre;
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d %d %d", &n, &k, &m)==3 &&
n!=0 && k!=0 && m!= 0)
{
init();
solve();
nCase++;
}
return 0;
}
以上是我的代码,纯用双向链表来模拟实现,既复杂又没有AC......郁闷的是我找了一个晚上都不知道错在哪里.....伤心了之后,去网上看到别人写的这些代码,我当时就跪了......
#include <cstdio>
#include <cstring>
const int maxn = 22;
int N;
bool d[maxn];
int cw(int pos, int k) {
int cnt = 0;
for ( ; cnt != k; pos++) {
if (pos == N) pos = 0;
if (d[pos]) cnt++;
}
return --pos;
}
int w(int pos, int m) {
int cnt = 0;
for (; cnt != m; pos--) {
if (pos == -1) pos = N - 1;
if (d[pos]) cnt++;
}
return ++pos;
}
int main() {
int k, m;
while (scanf("%d%d%d", &N, &k, &m) && N && k && m) {
memset(d, 1, N);
int tot = N, flag = 0, a = 0, b = N - 1;
while (tot) {
a = cw(a, k), b = w(b, m);
tot--;
if (flag) printf(",");
d[a] = d[b] = false;
flag = 1;
if (a == b)
printf("%3d", a + 1);
else {
printf("%3d%3d", a + 1, b + 1);
tot--;
}
}//while find out all
printf("\n");
}//while
return 0;
}
数组代替链表,布尔变量标记是否访问过............
尼玛,不活了!!!