题目概述:给你n个方块,有四种操作:
- move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面;
- move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上面;
- pile a onto b,把b上面的放回原来位置,然后把a和a上面的方块整体放到b上面;
- pile a over b,把a和a上面的方块整体放到b所在堆的上面。
Input
0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:
Output
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit
解题思路:
因为每个木块堆的高度不确定,所以用vector来保存很合适,而每个木块堆的个数不超过n,所以用一个一维数组来存就可以。
注意:
输入一共有4种指令,但如果完全独立地处理各指令,代码就会变得冗长而且容易出错。寻找提出指令之间的共同点,编写函数减少重复代码。
#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
using namespace std;
const int maxn = 30;
int n;
vector<int> pile[maxn];
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 代表 a 所在的 几行几列
}
}
}
}
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 移回原处
}
pile[p].resize(h+1); //重新改正 p 堆的大小(size)
}
void pile_onto(int p,int h,int p2){ // 把第 p 堆高度为 h 及其上方的木块整体移动到 p2 堆的顶部
for(int i = h;i < pile[p].size();i++){
pile[p2].push_back(pile[p][i]); //循环 把p堆上的每一个木块依次移到p2堆
}
pile[p].resize(h); //重置p堆的大小(size)
}
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;
scanf("%d",&n);
string s1,s2;
for(int i = 0;i < n;i++){
pile[i].push_back(i); //将各个木块依次放好初始位置
}
while(cin>>s1){
if(s1 == "quit"){ // quit 直接退出
break;
}
cin>>a>>s2>>b;
int pa,pb,ha,hb;
find_block(a,pa,ha); //查询,找到 a 所在的 堆 和其 高度
find_block(b,pb,hb);
if(pa == pb){ // a 和 b在同一堆,非法指令
continue; // 不执行
}
if(s1 == "move"){
clear_above(pa,ha);
}
if(s2 == "onto"){
clear_above(pb,hb);
}
pile_onto(pa,ha,pb);
}
print();
return 0;
}