• 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 这一条指令,上面的代码是修改版。

  • 相关阅读:
    箭头函数1
    变量结构赋值
    警惕32位程序在MethodImplOptions.Synchronized在x64机器上的同步缺陷[z]
    ListView的BeginUpdate()和EndUpdate()作用[z]
    如何用命令将本地项目上传到git[z]
    C# 两个datatable中的数据快速比较返回交集或差集[z]
    C# DataTable抽取Distinct数据(不重复数据)[z]
    【Thread】CountdownEvent任务并行[z]
    C#多线程--信号量(Semaphore)[z]
    VS2015一新建项目就出现未将对象引用设置到对象的实例怎么办?[z]
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/14207478.html
Copyright © 2020-2023  润新知