zoukankan      html  css  js  c++  java
  • UVa 101 木块问题 (The Blocks Problem)

    题目描述

    20201229142722

    image-20201229142835340

    关于上面的指令,说明如下:

    • 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 都是木块号码,把 b 上方的木块全部归位,然后把 a 及上面的木块整体摞在 b 上面。
    • pile a over b: 木块 a 和 b 都是木块号码,把 a 及上面的木块整体摞在 b 所在的木块堆的顶部。
    • quit: 终止操作。

    根据上面的样例输入,制作出如下的移动过程表,用来辅助理解。注意,下面的指令中,pile 8 over 6 是非法指令,根据上面的题目描述,我们只需将其忽略即可。

    ![20201229142626](E:VSCodeWorkspaceworkspace博客园算法竞赛入门经典读书笔记UVa 101.assets20201229142626.png)

    因为原紫书给出的样例很简陋,所以,我参照了原题的样例,给出了上面的动态移动过程模拟,这样题目的意思应该就一目了然了。

    代码

    #include<cstdio>
    #include<string>
    #include<vector>
    #include<iostream>
    using namespace std;
    
    const int maxn = 30; // 题目中给定的 n 范围:0 < n < 25
    int n; // 在主程序中手动输入
    vector<int> pile[maxn]; // 每个 pile[i] 是一个 vector
    
    // 找木块 a 所在的 pile 和 height,以引用的方式返回调用者
    void find_block(int a, int& p, int& h)
    {
        for (p = 0; p < n; p++)
        {
            for (h = 0; h < pile[p].size(); h++)
                if (pile[p][h] == a) return;
        }
    }
    
    // 把第 p 堆高度为 h 的木块上方的所有木块移回原位
    void clear_above(int p, int h)
    {
        for (int i = h + 1; i < pile[p].size(); i++)
        {
            int b = pile[p][i];
            pile[b].push_back(b); // 把木块 b 放回原位
        }
        pile[p].resize(h + 1); // pile 只应该保留下标 0 - h 的元素
    }
    
    // 把第 p 堆高度为 h 及其上方的木块整体移动到 p2 堆的顶部,书中函数命名为 pile_onto,我认为 Pile_over 更合适一点
    void pile_over(int p, int h, int p2)
    {
        for (int i = h; i < pile[p].size(); i++)
            pile[p2].push_back(pile[p][i]);
        pile[p].resize(h); // pile 只保留 0 到 h - 1 的元素
    }
    
    void print()
    {
        for (int i = 0; i < n; i++)
        {
            printf("%d:", i);
            for (int j = 0; j < pile[i].size(); j++)
                printf(" %d", pile[i][j]);
            printf("
    ");
        }
    }
    
    int main()
    {
        int a, b;
        cin >> n;
        string s1, s2;
        for (int i = 0; i < n; i++)
            pile[i].push_back(i);
        while (cin >> s1)
        {
            if (s1 == "quit") break;
            cin >> a >> s2 >> b;
            int pa, pb, ha, hb;
            find_block(a, pa, ha); // 找到 a 所在的堆 pa,和高度 ha
            find_block(b, pb, hb); // b
            if (pa == pb) continue; // 如果 a 和 b 在同一个堆,那么,本指令是非法指令,忽略
            if (s2 == "onto") clear_above(pb, hb);
            if (s1 == "move") clear_above(pa, ha);
            pile_over(pa, ha, pb);
        }
        print();
        return 0;
    }
    

    输出结果:

    20201229163550

    注意,紫书原来的代码没有考虑 quit 这一条指令,上面的代码是修改版。

  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/14207478.html
Copyright © 2011-2022 走看看