【PTA】C语言 木块移动

输入整数 n ,表示有编号为 1到n 的木块,分别放在顺序排列编号为 1~n 的位置。


设 x 和 y 是木块块号。现对这些木块进行操作,操作指令有如下四种:

• mov x to y :把 x 、 y 上的木块放回各自原来的位置,再把 木块x 放到木块 y 上;

• mov x on y :把 x 上的木块放回各自的原来的位置,再把 x 放到包含了 y 的木块堆上;

• shift x to y :把 y 上的木块放回各自的原来的位置,再把 x 以及在 x 上面的木块放到 y 上;

• shift x on y :把 x 连同 x 上木块放到包含了 木块y 的堆上。

• 当输入 quit 时,结束操作并输出 0~n-1 位置上的木块情况。

• 在操作指令中,如果 x = y ,其中 x 和 y 在同一堆块,则该操作指令是非法指令。非法指令要忽略,并且不应影响块的放置。

输入格式:

输入的第一行给出一个整数 n ,表示木块的数目。本题设定 0 < n <= 50 。

然后给出一系列操作指令,每行一个操作指令。您的程序要处理所有命令直到遇到 quit 指令。

本题设定,所有的操作指令都是上面给出的格式,不会有语法错误的指令。

输出格式:

输出给出木块的最终状态。每个原始块位置 i ( 0<=i<n ,其中 n 是木块的数目)之后给出一个冒号。如果在这一位置至少有一个木块,则冒号后面输出一个空格,然后输出在该位置的一个木块列表,每个木块编号与其他块编号之间用空格隔开。在一行结束时不要在结尾加空格。

每个块位置要有一行输出(也就是说,要有 n 行输出,其中 n 是第一行输入给出的整数)。

输入样例1:

5
quit 

输出样例1:

1: 1
2: 2
3: 3
4: 4
5: 5

输入样例2:

9
mov 9 to 1
mov 8 on 1
mov 7 on 1
mov 6 on 1
shift 8 on 6
shift 8 on 5
shift 2 on 1
shift 4 on 9
quit

输出样例2:

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

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>

#define maxn 30

int n;
int pile[maxn][maxn];
int pile_size[maxn];

//找到木块a所在的pile和height,以引用的形式返回调用者
void find_block(int a, int* p, int* h)
{
    int i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < pile_size[i]; j++) {
            if (pile[i][j] == a) {
                *p = i;
                *h = j;
                return;
            }
        }
    }
    *p = *h = -1; // not found
}

//把第p堆高度为h的木块上方的所有木块移回原位
void clear_above(int p, int h)
{
    int i;
    for (i = pile_size[p] - 1; i > h; i--) {
        int b = pile[p][i];
        pile[b][pile_size[b]] = b;
        pile_size[b]++;
        pile_size[p]--;
    }
}

//把第p堆高度为h及其上方的木块整体移动到p2堆的顶部
void pile_onto(int p, int h, int p2)
{
    int i;
    for (i = h; i < pile_size[p]; i++) {
        int b = pile[p][i];
        pile[p2][pile_size[p2]] = b;
        pile_size[p2]++;
    }
    pile_size[p] = h;
}

void print()
{
    int i, j;
    for (i = 0; i < n; i++) {
        printf("%d:", i+1);
        for (j = 0; j < pile_size[i]; j++)
            printf(" %d", pile[i][j] + 1);
        printf("\n");
    }
}

int main()
{
    int a, b;
    char s1[5], s2[5];
    int pa, pb, ha, hb;
    int i, j;
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        pile[i][0] = i;
        pile_size[i] = 1;
    }
    while (scanf("%s%d%s%d", s1, &a, s2, &b) == 4) {
        if (strcmp(s1, "quit") == 0) break;
        find_block(a - 1, &pa, &ha);
        find_block(b - 1, &pb, &hb);
        if (pa == pb) continue;
        if (strcmp(s2, "onto") == 0) clear_above(pb, hb);
        if (strcmp(s1, "move") == 0) clear_above(pa, ha);
        pile_onto(pa, ha, pb);
    }
    print();
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值