Files
python/RuMenJingDian/UVa/UVa101.cpp

94 lines
3.6 KiB
C++
Raw Normal View History

2025-08-30 18:35:01 +08:00
#include <bits/stdc++.h>
using namespace std;
//https://blog.csdn.net/weixin_30516243/article/details/95800585
//https://www.luogu.com.cn/problemnew/solution/UVA101?page=2
/**
总的来说就是碰到move就要把a上面的全部放回原处。
如果碰到 onto 就要把b上面的全部放到原处。 因为move是只移动a一个,
所以a上面的要归位,而pile是移一堆,所以不用。
onto是要和b贴在一起,所以b上面的要归位,而over是上方,不需要直接接触,
所以不用。。思路就是用栈来模拟,一开始就是n个栈。每个栈里都是一个元素,然后按照指令移,
在这个栈里pop()掉它,在另一个栈里push()进去。。 分四种情况来做移动,
每种情况处理方式不一样。要注意如果是一堆移过去,因为还是要按照这个顺序,
多以要先把这一堆放到另一个数组,再按顺序pushj进去。 模拟完输出即可。。
*/
const int maxn = 30;
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++) //进入某个堆后,一个个开始查找,从下向上找
//如果找到,返回所在的堆p和高度h,通过&p和&h可以直接将数据修改后返回到主函数
if (pile[p][h] == a)
return;
}
//把第p堆高度为h的木块上方的所有木块移回原位
void clear_above(int p, int h) {
//找到p堆h高度以上的所有木块
for (int i = h + 1; i < pile[p].size(); i++) {
int b = pile[p][i];
pile[b].push_back(b); //把木块b放回原位堆
}
//更改大小,相当于删除了vector里面多余的元素
pile[p].resize(h + 1); //pile只应保留下标0~h的元素
}
//把第p堆高度为h及其上方的木块整体移动到p2堆的顶部
void pile_onto(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);
}
//输出结果
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;
//共n堆,每堆1个,计为i号林块(0<=i<n),所以有两个概念,
// 一个是第几堆,一个是第几块,最开始是一样的数字,即 i=1时,第1堆里放着第1块木块
//但是随着移动变化,堆不变,但块会被移走或被其它林块盖上。
for (int i = 0; i < n; i++)
pile[i].push_back(i);
//读入命令
while (cin >> s1 >> a >> s2 >> b) {
int pa, pb, ha, hb;
//pa-->查找现在a木块存在于哪一堆内?
//ha-->a木块所在的高度,即索引号
find_block(a, pa, ha);
//同上
find_block(b, pb, hb);
//如果同一堆就不能动了,非法指令
if (pa == pb)
continue; //非法指令
//下面开始把共有的部分进行了抽象,节约代码
if (s2 == "onto")
clear_above(pb, hb);
if (s1 == "move")
clear_above(pa, ha);
pile_onto(pa, ha, pb);
}
//输出结果
print();
return 0;
}