标签:入门经典 name 输入 using 目的 笔记 vsc 经典 算法
关于上面的指令,说明如下:
根据上面的样例输入,制作出如下的移动过程表,用来辅助理解。注意,下面的指令中,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