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.
#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; }
#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; }
数组代替链表,布尔变量标记是否访问过............
尼玛,不活了!!!