uva 133 - The Dole Queue

题目不难,属于模拟类型的题目,需要比较仔细地处理各种边界情况。估计题目的本意是想让我们实现一个双向循环链表,我看了下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;
}

 

 

 

你可能感兴趣的:(acm)