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

  • 相关阅读:
    Eclipse部署项目到Tomcat中,class文件夹为空的解决方案
    微软(北京).NET俱乐部活动 (2010年6月26日) – Visual Studio 2010 /*LIFE RUNS ON CODE*/
    失望的Vista SP1
    急聘BI DW OLAP开发工程师 (北京)
    急聘.NET开发工程师 (北京)
    开篇
    Windows Vista User Account Control (UAC) 全新安全模块“用户帐户控制”
    Tidy your desktop
    [导入]Vista的屏幕截图小工具:Snipping Tool
    微软发布官方TFS 2010 Scrum 模板
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/14207478.html
Copyright © 2011-2022 走看看