题目:https://www.luogu.com.cn/problem/UVA101
测试样例:https://www.udebug.com/UVa/101
这道题是紫书上介绍C++中的vector容器的例题,是一道典型的vector入门题,所以这个题解的做法是vector的。
题是个模拟,方法很容易想到,具体做法大家已经说得很详细了,我就来说说这道题个人认为的一些注意事项和坑(打了2h,踩坑不断)吧。
1. 输出格式中的空格问题。这个不多说了。
2. 正确理解“归位”:
这道题背景是机器人搬重物:有n个箱子,编号为0~n-1,最初是一字排开的,占据0~n-1的这n个位置,然后给你4种操作,经过多次操作后,让你打印每个位置上箱子的堆放顺序。
在一些操作中,出现了“归位”的概念,你可能心想“归位”就要把箱子放在和它初始位置完全相同的地方,也就是编号对应位置那堆箱子的最底下。其实不是这样的
比如把5号箱归位,而5号位置目前从下到上堆放着编号为3、4、2的箱子,正确的操作后,这堆箱子的编号(从下到上)不是5、3、4、2,而是3、4、2、5,也就是说“归位”一个箱子,只需要把它堆在其编号对应的位置的顶端就可以了。
3. 非法情况
读原题就可知,待操作的两个箱子编号若满足\(a=b\),则为非法;
对于任何一个操作,如果待操作的两个箱子都在一个位置(也就是同一堆)的话,那么这个操作也是非法的。注意是任何一个操作。对于部分操作,虽然可以构造出来两个箱子在一堆,也能成功进行操作的样例,但是也存在非法的情况,这些非法情况会让vector越界而导致段错误(RE)。
所以不论如何,只要出现上述情况,都是非法的。
4. 给一堆箱子正确归位后,它们的顺序是不变的,不是倒过来的
想象一下,搬一摞箱子嘛,12345换个地方还是12345,不是54321。所以得再开个vector作为中介,对那堆箱子进行出栈进栈操作,使得顺序不变。
5.size()是会随着push和pop操作不断变化的
现在某个位置有7个箱子,从下往上编号:a,b,c,d,e,f,g。我要把b箱上面的所有箱子归位。
现在已经查找到b箱子是从下到上的第t个箱子(在这个例子,t=2)
写成for循环:
for(int i=1;i<=s[p].size()-t;i++){
int tp=s[p].back();
s[p].pop_back();
s[tp].push_back(tp);
}
看出来哪里不对了吗?进行归位的操作的次数,难道不是最开始vector的长度减去t吗?
确实是,然而要知道,随着push、pop, s[p].size()
也在变化!循环的次数会小于正确的次数!
正确的写法:
int len=s[p].size()-t;//获取最开始s[p]的长度
for(int i=1;i<=len;i++){
int tp=s[p].back();
s[p].pop_back();
s[tp].push_back(tp);
}
这样才能保证你的循环运行正确的次数。