题目:给你n个方块,有四种操作:

            1.move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面;

            2.move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上面;

            3.pile a onto b,把b上面的放回原来位置,然后把a和a上面的方块整体放到b上面;

            4.pile a over b,把a和a上面的方块整体放到b所在堆的上面。

分析:观察操作,如果是move就是先把a上面的还原,如果是onto就是先把b上面的还原。然后,就是移动一堆到另一堆的上面(单个也认为是一堆)。所以只需要两个基础操作:

            1.将a上面的还原init(a);

            2.将a和上面的(可以没有上面的)放到b上面pile_a_To_b(a,b)。

            那么上述的四组操作就变成下面了:

            1.move a onto b,init(a);init(b);pile_a_To_b(a,b);

            2.move a over b,init(a);pile_a_To_b(a,b);

            3.pile a onto b,init(b);pile_a_To_b(a,b);

            4.pile a over b,pile_a_To_b(a,b)。

注意:如果a和b已经在一堆中就不要操作,此时认为不用移动,否则会WA。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
int num[25];
int stack[25][25];
int place[25];
//将位置a上的放回原处
void init(int a){
	int block, id = place[a];
	while (stack[id][num[id]] != a){
		block = stack[id][num[id]--];
		place[block] = block;
		stack[block][++num[block]] = block;
	}
}

//将a和上面的全都移到b上
int tmp[25];
void pile_a_To_b(int a, int b){
	int top = -1, ida = place[a], idb = place[b];
	while (stack[ida][num[ida]] != a)
		tmp[++top] = stack[ida][num[ida]--];
	place[a] = idb;
	stack[idb][++num[idb]] = a;
	num[ida]--;
	while (top >= 0){
		place[tmp[top]] = idb;
		stack[idb][++num[idb]] = tmp[top--];
	}
}
int main(){
	int n, a, b;
	char str1[5], str2[5];
	while (~scanf("%d", &n)){
		for (int i = 0; i < n; i++){
			stack[i][0] = i;
			place[i] = i;
			num[i] = 0;
		}
		while (scanf("%s", str1) && str1[0] != 'q'){
			scanf("%d%s%d", &a, str2, &b);

			if (place[a] == place[b])
				continue;
			if (str1[0] == 'm')
				init(a);
			if (str2[1] == 'n')
				init(b);
			pile_a_To_b(a, b);
		}
		for (int i = 0; i < n; i++){
			printf("%d:", i);
			int m = 0;
			while (m <= num[i])
				printf(" %d", stack[i][m++]);
			puts("");
		}
	}
	return 0;
}