码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 101 木块问题 (The Blocks Problem)

时间:2021-01-02 11:14:16      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:入门经典   name   输入   using   目的   笔记   vsc   经典   算法   

题目描述

技术图片

技术图片

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

  • 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:\VSCodeWorkspace\workspace\博客园\算法竞赛入门经典读书笔记\UVa 101.assets\20201229142626.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("\n");
    }
}

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;
}

输出结果:

技术图片

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

UVa 101 木块问题 (The Blocks Problem)

标签:入门经典   name   输入   using   目的   笔记   vsc   经典   算法   

原文地址:https://www.cnblogs.com/fanlumaster/p/14207478.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!