POJ(1208)The Blocks Problem——(链表)

题目地址:

http://poj.org/problem?id=1208

 

The Blocks Problem

问题描述:

问题是解析一系列命令,指示机器人手臂如何操纵位于平台上的块。 最初在表上有n个块(编号从0到n-1),块bi与块bi + 1相邻,所有0 <= i <n-1,如下图所示:

操纵块的机器人手臂的有效命令是:


move a onto b:
其中A和B是块编号,在将堆积在块A和B顶部的任何块返回到它们的初始位置之后,将块A放到块B上。

move a over b:
其中A和B是块编号,在将块A顶部堆叠的任何块返回到其初始位置之后,将块A放入包含块b的堆栈的顶部。

pile a onto b:

其中A和B是块编号,移动由块A组成的块堆,以及堆积在块A上方的任何块到块B上。 在堆发生之前,块B顶部的所有块都移动到它们的初始位置。 上面堆叠的块在移动时保持其顺序。

pile a over b:

其中A和B是块编号,将由块A组成的块堆和堆积在块A上方的任何块放到包含块B的堆栈顶部。 块上方堆叠的块在移动时保留其原始顺序。

quit:

终止块世界中的操作。

任何A = B或其中A和B在同一堆块中的命令都是非法命令。 应忽略所有非法命令,并且不应影响块的配置。

 

输入描述:

 

输入以行上的整数n开始,表示块世界中的块数。 您可以假设0 <n <25。
块的数量后跟一系列块命令,每行一个命令。 您的程序应该处理所有命令,直到遇到quit命令。

您可以假设所有命令都是上面指定的格式。 没有语法错误的命令。

 

输出描述:

输出应该包含块世界的最终状态。 应该出现编号为i(0 <= i <n,其中n是块数)的每个原始块位置,紧接着是冒号。 如果它上面至少有一个块,则冒号后面必须跟一个空格,后面跟着一个块列表,这些块表示堆叠在该位置,每个块号与其他块号分隔一个空格。 不要在行上放置任何尾随空格。

每个块位置应该有一行输出(即,n行输出,其中n是第一行输入上的整数)。

 

样例输入:

10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit

样例输出:

0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:

 

思路:

我的思路是使用多条链表来解决。链表的每个节点的数据类型为一个结构体node,结构体内有两个基本数据类型成员:一个整型data(用来存放木块的编号),和一个指向node的指针next(用来存放下一个木块的地址)。 然后,在每个木块初始位置上都设置一条链表(一条链表就表示为这个位置上的木块放置情况,节点表示木块儿,并且认为靠近链表头节点的节点是较下方的木块。),也就是n条链表,例如输入样例,程序就会生成10条链表。每个链表的初始化为:链表中只有一个节点,这个节点的data为这个位置的编号,这个节点的next为NULL,例如,位置3上的链表初始化后只有一个节点,data为3,next为NULL。并且认为靠近链表头节点的节点是较下方的木块。

接下来输入n和命令字符串,根据命令字符串来选择4个程序中的1个来执行。

当命令为 move A onto B:

根据题意,先将A和B木块上面木块都归位,就是说,将A节点的后面的节点都去掉,并放回编号为它们各自本身的位置的链表。具体操作为:首先,先将a木块上方木块归位,从a节点往后遍历这条链表,对每个遍历到的节点:next设为NULL,并将编号为“该节点的data”的链表的链表头节点设置为该节点。然后将a节点的next设为NULL。a木块上面木块就归位完毕了。对b节点同理。此时已经将ab木块上面的木块放回了初始位置,接下来,只需要将b节点的next指向a节点(意义为将a木块放在b木块上),并且将指向b节点的节点next设为NULL(如果没有指向b节点的节点,就将初始时所在的那条链表头节点设置为NULL,即设为空链表)(这个操作的意义为更新链表的尾节点), 完成。

当命令为move A over B:

跟上一个不同的是,这回不需要将b木块上面的木块放回初始位置,因为是将a木块放在b木块所在块堆的最顶上。    a木块上面的木块还是需要放回初始位置,方法和上文相同。接下来,a木块上已经没有木块,看b节点所在链表,找到该链表的尾节点,将尾节点的next指向a木块就完成了(意义为将a木块放在b木块块堆上), 并将指向a节点的节点next设为NULL(如果没有指向a节点的节点,就将初始位置的那条链表头节点设置为NULL,即设为空链表)(这个操作的意义为更新链表的尾节点), 完成。

当命令为pile A onto B:

跟第一个不同的是,这回不需要将a木块上面的木块放回初始位置,因为是将a木块以及a木块以上的所有木块全部拿起,放在b木块上。 b木块上面的木块还是需要放回初始位置,方法和上文相同。现在,b木块上已经没有木块。接下来,将a木块块堆拿起,即把指向a节点的节点的next设置为NULL。然后放在b木块上,即将b节点的next指向a节点, 完成。

当命令为pile A onto B:

这个命令应该是最简单的,因为这回对ab木块,都不需要将上面的木块放回初始位置了。所以用同样的方法找到b节点的所在链表的链表尾节点,然后把a节点和后边所有节点这个部分链,接在找到的尾节点上,就完成了。

 

需要注意的是:

1.这道题还需要判断命令是否合法(如果ab在一个链表里就不合法了)。我的方法是:在执行命令之前,判断ab所在链表的链表尾节点是否相同,相同即不合法,不相同即合法。

2.在执行每条命令之前,需要找到四个地址,存到指针里,分别为a节点的地址,指向a节点的节点的地址,b节点的地址,指向b节点的节点的地址。

 

另外写代码有点略长,不够精炼,有些地方可能不够专业,毕竟刚大一,有错误或者重复计算的地方,希望大家能指出,谢谢~

还有,这里题目描述都是google翻译的,原文在上文网址中。。。

 

ac代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

struct node
{
    int data;
    struct node *next;
};

int main()
{
    struct node *p, *q, *t, *head[30], *pa, *pb, *qa, *qb, *tt;
    int i, j, d, n;
    scanf("%d", &n);
    qa = NULL;
    qb = NULL;
    for(i = 0; i <= n-1; i++)
    {
        p = (struct node *)malloc(sizeof(struct node));
        p -> data = i;
        p -> next = NULL;
        head[i] = p;
    }
    char aa[10], bb[10];
    int a, b;
    getchar();
    while(scanf("%s", aa))
    {
        qa = NULL;
        qb = NULL;
        if(strcmp(aa, "quit") == 0)
        {
            break;
        }
        scanf("%d%s%d",&a, bb, &b);
        if(a == b)
            continue;
        for(i = 0; i <= n-1; i++)
        {
            t = head[i];
            while(t != NULL)
            {
                if(t->data == a)
                {
                    pa = t;
                }
                if(t->next != NULL && t->next->data == a)
                {
                    qa = t;
                }
                if(t->data == b)
                {
                    pb = t;
                }
                if(t->next != NULL && t->next->data == b)
                {
                    qb = t;
                }
                t = t->next;
            }
        }

        struct node *ta, *tb;
        ta = pa;
        while(ta->next != NULL)
        {
            ta = ta->next;
        }
        tb = pb;
        while(tb->next != NULL)
        {
            tb = tb->next;
        }
        if(ta == tb)
            continue;

        if(strcmp(aa, "move") == 0)
        {
            if(qa != NULL)
            {
                qa->next = NULL;
            }
            else
            {
                head[pa->data] = NULL;
            }
            t = pa->next;
            while(t != NULL)
            {
                head[t->data] = t;
                tt = t->next;
                t->next = NULL;
                t = tt;
            }
            if(strcmp(bb, "onto") == 0)
            {
                t = pb->next;
                while(t != NULL)
                {
                    head[t->data] = t;
                    tt = t->next;
                    t->next = NULL;
                    t = tt;
                }
                pb->next = pa;
            }
            else if(strcmp(bb, "over") == 0)
            {
                t = pb;
                while(t->next != NULL)
                {
                    t = t->next;
                }
                t->next = pa;
                pa->next = NULL;

            }
        }
        else if(strcmp(aa, "pile") == 0)
        {
            if(qa != NULL)
            {
                qa->next = NULL;
            }
            else
            {
                head[pa->data] = NULL;
            }
            if(strcmp(bb, "onto") == 0)
            {
                t = pb->next;
                while(t != NULL)
                {
                    head[t->data] = t;
                    tt = t->next;
                    t->next = NULL;
                    t = tt;
                }
                pb->next = pa;

            }
            else if(strcmp(bb, "over") == 0)
            {
                t = pb;
                while(t->next != NULL)
                {
                    t = t->next;
                }
                t->next = pa;
            }
        }
    }
    for(j = 0; j <= n-1; j++)
    {
        t = head[j];
        printf("%d:", j);
        while(t != NULL)
        {
            printf(" %d", t->data);
            t = t->next;
        }
        printf("\n");
    }

    return 0;
}

 

 

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值