UVA101 木块问题 解题报告
题目链接
https://vjudge.net/problem/UVA-101
题目大意
从左到右有n个木块,编号为0~n-1,要求模拟以下4种操作(下面的a和b都是木块编号)。
move a onto b:把a和b上方的木块全部归位,然后把a摞在b上面。
move a over b:把a上方的木块全部归位,然后把a放在b所在木块堆的顶部。
pile a onto b:把b上方的木块全部归位,然后把a及上面的木块整体摞在b上面。
pile a over b:把a及上面的木块整体摞在b所在木块堆的顶部。
遇到quit时终止一组数据。a和b在同一堆的指令是非法指令,应当忽略。
解题思路
直接硬模拟代码会比较冗长,我们可以抽象提取一下几个命令的公共操作封装成函数,详细见代码和注释。
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
#define endl '\n';
const int maxn = 1e3 + 10;
const int INF = 0x3fffffff;
const int mod = 1e9 + 7;
vector<int> pile[maxn];
int n;
void init() {
for (int i = 0; i < n; i++) {
pile[i].push_back(i);
}
}
// 找到木块a所在的堆编号以及高度
void findBlock(int a, int &p, int &h) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < pile[i].size(); j++) {
if (pile[i][j] == a) {
p = i;
h = j;
return;
}
}
}
}
// 把第p堆,高度为h的木块上方的所有木块归位
void putBack(int p, int h) {
for (int i = h + 1; i < pile[p].size(); i++) {
int b = pile[p][i];
pile[b].push_back(b);
}
pile[p].resize(h + 1);
}
// 把第p堆,高度为h及以上的木块,挪动到第p2堆上
void moveBlock(int p, int h, int p2) {
for (int i = h; i < pile[p].size(); i++) {
int b = pile[p][i];
pile[p2].push_back(b);
}
pile[p].resize(h);
}
void solve() {
cin >> n;
init();
string op1, op2;
int a, b;
while (cin >> op1, op1 != "quit") {
cin >> a >> op2 >> b;
int pa, ha, pb, hb;
findBlock(a, pa, ha);
findBlock(b, pb, hb);
if (pa == pb)
continue;
if (op1 == "move") {
putBack(pa, ha);
if (op2 == "onto") {
putBack(pb, hb);
}
moveBlock(pa, ha, pb);
} else {
if (op2 == "onto") {
putBack(pb, hb);
}
moveBlock(pa, ha, pb);
}
}
for (int i = 0; i < n; i++) {
cout << i << ":";
for (int j = 0; j < pile[i].size(); j++) {
cout << " " << pile[i][j];
}
cout << endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout << fixed;
cout.precision(18);
int Case = 1;
// cin >> Case;
while (Case--)
solve();
return 0;
}