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

  • 相关阅读:
    CREATE AGGREGATE
    技术文档列表
    jQuery 判断表单中多个 input text 中至少有一个不为空
    Java实现 蓝桥杯 算法提高 奥运会开幕式
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最大值路径
    Java实现 蓝桥杯 算法提高 最大值路径
    Java实现 蓝桥杯 算法提高 最大值路径
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/14207478.html
Copyright © 2011-2022 走看看