UVaOJ 101 - The Blocks Problem

——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

用顺序表,即建立两个数组,分别用来存储:
  • 以某个积木为底的积木堆。
  • 某块积木的位置。
模拟的时候注意维护两个数组即可。
这道题目除了可以用顺序表,还可以用双向链表来做。

UVaOJ 101 - The Blocks Problem_第1张图片

如果用双向链表,则需要维护:
  • 每个节点的状态。
  • 表示初始位置的节点的状态。
  • 积木的位置。

本来对于这种大量的成段数据移动,用双向链表会较快,但是因为有无效指令,导致每次移动都要遍历去维护积木的位置,使得双向链表和顺序表的做法效率差不多。

为了练习双向链表的使用,我用的是双向链表,并且是动态开辟空间的做法。

如果单纯为了 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");
    }
}



下载PDF

参考资料:无

你可能感兴趣的:(UVaOJ 101 - The Blocks Problem)