——by A Code Rabbit
Description
平台上摆放着个 n 个积木(编号由 0 到 n – 1),初始位置为 0 到 n - 1。

你要模拟一个机械手臂的操作,机械手臂有四种指令:
- move a onto b:将 a 和 b 上的积木都放回初始位置,然后把 a 放在 b 上(a、b 紧贴着)。
- move a over b:将 a 上的积木放回初始位置,然后把 a 放在 b 堆上(a、b 隔开的)。
- pile a onto b: 将 b 上的积木放回初始位置, 然后把 a 堆放到 b 上(a、b 紧贴着)。
- pile a over b:把 a 堆 放在 b 堆上(a、b 隔开的)。
- quit:结束操作。
- 注意当 a 和 b 在同一堆的时候,指令无效。
Types
Date Structure :: Lists
Analysis
用顺序表,即建立两个数组,分别用来存储:
- 以某个积木为底的积木堆。
- 某块积木的位置。
这道题目除了可以用顺序表,还可以用双向链表来做。

- 每个节点的状态。
- 表示初始位置的节点的状态。
- 积木的位置。
本来对于这种大量的成段数据移动,用双向链表会较快,但是因为有无效指令,导致每次移动都要遍历去维护积木的位置,使得双向链表和顺序表的做法效率差不多。
为了练习双向链表的使用,我用的是双向链表,并且是动态开辟空间的做法。
如果单纯为了 AC,推荐用顺序表来做。
Solution
// UVaOJ 101
// The Blocks Problem
// by A Code Rabbit
#include <cstdio>
#include <cstring>
const int LIMITS = 100;
struct Node {
Node* pred;
int val;
Node* succ;
};
int n;
char command[100];
char first_word[20];
char second_word[20];
int a, b;
Node* head[LIMITS];
Node* block[LIMITS];
int pos[LIMITS];
void INIT();
void ReturnOriginalPos(Node *p);
void Connect(Node* a, Node* b);
void MoveAOntoB(Node* a, Node* b);
void MoveAOverB(Node* a, Node* b);
void PileAOntoB(Node* a, Node* b);
void PileAOverB(Node* a, Node* b);
void Outputs();
int main() {
while (scanf("%d", &n) != EOF) {
getchar();
// INIT.
INIT();
// Inputs and operating.
while (scanf("%s", first_word)){
if (strcmp(first_word, "quit") == 0) {
break;
}
gets(command);
sscanf(command, "%d%s%d", &a, second_word, &b);
if (pos[a] != pos[b]) {
if (strcmp(first_word, "move") == 0) {
if (strcmp(second_word, "onto") == 0) {
MoveAOntoB(block[a], block[b]);
} else
if (strcmp(second_word, "over") == 0) {
MoveAOverB(block[a], block[b]);
}
} else
if (strcmp(first_word, "pile") == 0) {
if (strcmp(second_word, "onto") == 0) {
PileAOntoB(block[a], block[b]);
} else
if (strcmp(second_word, "over") == 0) {
PileAOverB(block[a], block[b]);
}
}
}
}
// Outputs.
Outputs();
// Release all pointers.
for (int i = 0; i < n; ++i) {
delete block[i];
delete head[i];
}
}
return 0;
}
void INIT() {
for (int i = 0; i < n; ++i) {
head[i] = new Node;
block[i] = new Node;
head[i]->pred = NULL;
head[i]->val = -1;
head[i]->succ = block[i];
block[i]->pred = head[i];
block[i]->val = i;
block[i]->succ = NULL;
pos[i] = i;
}
}
void ReturnOriginalPos(Node* p) {
if (p == NULL) {
return;
}
ReturnOriginalPos(p->succ);
p->pred = head[p->val];
p->succ = NULL;
head[p->val]->succ = p;
pos[p->val] = p->val;
}
void Connect(Node* a, Node* b) {
a->pred->succ = NULL;
a->pred = b;
b->succ = a;
pos[a->val] = pos[b->val];
}
void MoveAOntoB(Node* a, Node* b) {
ReturnOriginalPos(a->succ);
ReturnOriginalPos(b->succ);
a->succ = NULL;
Connect(a, b);
}
void MoveAOverB(Node* a, Node* b) {
ReturnOriginalPos(a->succ);
a->succ = NULL;
Node* b_tail = b;
while (b_tail->succ != NULL) {
b_tail = b_tail->succ;
}
Connect(a, b_tail);
}
void PileAOntoB(Node* a, Node* b) {
ReturnOriginalPos(b->succ);
Connect(a, b);
Node* p = a->succ;
while (p != NULL) {
pos[p->val] = pos[b->val];
p = p->succ;
}
}
void PileAOverB(Node* a, Node* b) {
Node* b_tail = b;
while (b_tail->succ != NULL) {
b_tail = b_tail->succ;
}
Connect(a, b_tail);
Node* p = a->succ;
while (p != NULL) {
pos[p->val] = pos[b->val];
p = p->succ;
}
}
void Outputs() {
for (int i = 0; i < n; ++i) {
printf("%d:", i);
Node* p = head[i]->succ;
while (p != NULL) {
printf(" %d", p->val);
p = p->succ;
}
printf("\n");
}
}
参考资料:无
524

被折叠的 条评论
为什么被折叠?



