题目不难,属于模拟类型的题目,需要比较仔细地处理各种边界情况。估计题目的本意是想让我们实现一个双向循环链表,我看了下N的值最大20,所以想先用数组实现试试,基本思路也是在数组里双向循环,删除的元素标记下;双向循环链表实现就比较好理解了,但是实现起来有些麻烦,指针神马的很容易搞错,需要非常仔细。
开始提交超时了,原因分析了下是因为:虽然N的值不大,但是k和m可以很大,所以找下k/m个的时候需要mod一下当前queue的size。
数组实现:
#include#define MAX 30 /* * status 0 means normal, status 1 means deleted * */ typedef struct Node { int num; int status; } Node; /* * startIdx1,startIdx2 mark the starting point of each round of picking. * */ typedef struct Queue { Node elements[MAX]; int size; int startIdx1; int startIdx2; } Queue; int n, k, m; Queue queue; void printQue() { int i; for (i = 0; i < n; i++) { printf("%d:[%d,%d] ", i, queue.elements[i].num, queue.elements[i].status); } printf("size:%d\n", queue.size); } int getNextIdx(int current) { int result = current + 1; if (result == n) result = 0; return result; } int getPreIdx(int current) { int result = current - 1; if (result < 0) result = n - 1; return result; } int pickFirst(int idx) { int currentIdx = idx; int count = 1; int num = k % queue.size; if (num == 1 || (queue.size == 1)) return currentIdx; if (num == 0) num = queue.size; while (1) { currentIdx = getNextIdx(currentIdx); if (queue.elements[currentIdx].status != 1) count++; if (count == num) { return currentIdx; } } } int pickSecond(int idx) { int currentIdx = idx; int count = 1; int num = m % queue.size; if (num == 1 || (queue.size == 1)) return currentIdx; if (num == 0) num = queue.size; while (1) { currentIdx = getPreIdx(currentIdx); if (queue.elements[currentIdx].status != 1) count++; if (count == num) { return currentIdx; } } return 0; } void pick() { int firstPick = pickFirst(queue.startIdx1); int secondPick = pickSecond(queue.startIdx2); queue.elements[firstPick].status = 1; queue.elements[secondPick].status = 1; if (firstPick == secondPick) queue.size -= 1; else queue.size -= 2; if (firstPick != secondPick) printf("%3d%3d", queue.elements[firstPick].num, queue.elements[secondPick].num); else printf("%3d", queue.elements[firstPick].num); if (queue.size > 0) printf(","); else printf("\n"); if (queue.size <= 0) return; int nextStartIdx1 = getNextIdx(firstPick); while (queue.elements[nextStartIdx1].status == 1) nextStartIdx1 = getNextIdx(nextStartIdx1); int nextStartIdx2 = getPreIdx(secondPick); while (queue.elements[nextStartIdx2].status == 1) nextStartIdx2 = getPreIdx(nextStartIdx2); queue.startIdx1 = nextStartIdx1; queue.startIdx2 = nextStartIdx2; } int main() { /* setbuf(stdout,NULL);*/ while (scanf("%d%d%d", &n, &k, &m) != EOF) { if (n == 0) break; queue.size = n; queue.startIdx1 = 0; queue.startIdx2 = n - 1; int i; for (i = 0; i < n; i++) { queue.elements[i].num = i + 1; queue.elements[i].status = 0; } while (queue.size > 0) { pick(); } } return 0; }
链表实现:
#include#include #define MAX 30 struct Node; typedef struct Node* PtrToNode; typedef struct Node { int num; PtrToNode next; PtrToNode pre; } Node; typedef struct Queue { PtrToNode head; int size; PtrToNode startIdx1; PtrToNode startIdx2; } Queue; int n, k, m; Queue queue; Queue *que = &queue; void printQueue() { int i; PtrToNode cur = que->head; for (i = 0; i < que->size; i++) { printf("%d ", cur->num); cur = cur->next; } printf("size:%d,idx1:%d,idx2:%d", que->size, que->startIdx1->num, que->startIdx2->num); printf("\n"); } void makeQueue() { PtrToNode head = (PtrToNode) malloc(sizeof(Node)); head->num = 1; head->next = head; head->pre = head; que->head = head; que->size = n; que->startIdx1 = head; que->startIdx2 = head; if (n == 1) return; PtrToNode pre = head; int i; for (i = 1; i < n; i++) { PtrToNode current = (PtrToNode) malloc(sizeof(Node)); current->num = i + 1; current->pre = pre; pre->next = current; if (i == n - 1) { current->next = head; head->pre = current; } pre = current; } que->startIdx1 = head; que->startIdx2 = head->pre; } PtrToNode getNextNNode(PtrToNode p, int n) { int i; int size = n % que->size; PtrToNode result = p; for (i = 0; i < size; i++) { result = result->next; } return result; } PtrToNode getPreNNode(PtrToNode p, int n) { int i; int size = n % que->size; PtrToNode result = p; for (i = 0; i < size; i++) { result = result->pre; } return result; } /* * type 0 means removing the first pick. * type 1 means removing the second pick. * type 2 means removing the same item when first pick equals second pick. * * */ int removeNode(PtrToNode p, int type) { if (p == NULL ) return -1; int num = p->num; if (p == que->head) que->head = p->next; if (p == que->startIdx1) que->startIdx1 = p->next; if (p == que->startIdx2) que->startIdx2 = p->pre; if (type == 2) { que->startIdx1 = p->next; que->startIdx2 = p->pre; } else if (type == 0) { que->startIdx1 = p->next; } else { que->startIdx2 = p->pre; } p->pre->next = p->next; p->next->pre = p->pre; free(p); que->size--; return num; } void pick() { PtrToNode first = getNextNNode(que->startIdx1, k - 1); PtrToNode second = getPreNNode(que->startIdx2, m - 1); int one, two; if (first == second) { one = two = removeNode(first, 2); } else { one = removeNode(first, 0); two = removeNode(second, 1); } if (one != two) printf("%3d%3d", one, two); else printf("%3d", one); if (que->size > 0) printf(","); else printf("\n"); } int main() { /* setbuf(stdout,NULL);*/ while(scanf("%d%d%d",&n,&k,&m)!=EOF) { if(n==0) break; makeQueue(); while(que->size>0) { pick(); } } return 0; }