题目描述
设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号。将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A、B、C,这个状态称为初始状态。
现在要求找到一种步数最少的移动方案,使得从初始状态转变为目标状态。
移动时有如下要求:
·一次只能移一个盘;
·不允许把大盘移到小盘上面。
输入输出格式
输入格式:
文件第一行是状态中圆盘总数;
第二到第四行分别是初始状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号;
第五到第七行分别是目标状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号。
输出格式:
每行一步移动方案,格式为:move I from P to Q
最后一行输出最少的步数。
输入输出样例
输入样例#1:
5 3 3 2 1 2 5 4 0 1 2 3 5 4 3 1 1
输出样例#1:
move 1 from A to B move 2 from A to C move 1 from B to C move 3 from A to B move 1 from C to B move 2 from C to A move 1 from B to C 7
说明
圆盘总数≤45
每行的圆盘描述是从下到上的圆盘编号
解题思路
事先声明,博主没有解决第11个点,是打表过的。以下是本蒟蒻通过前十个点的思路。
按照从大到小的顺序让圆盘归位,假设x要从1柱到2柱,那么就让所有比x小的都先到3柱,然后把x从1柱放到2柱。具体实现见代码及注释。
代码如下
#include <iostream>
#include <cstdio>
#include <queue>
#define maxn 50
using namespace std;
int loc[maxn]; //i的当前位置
int obj[maxn]; //i的目标位置
struct step{
int num, from, to; //1为A,2为B,3为C
step(int n, int f, int t): num(n), from(f), to(t){ }
};
queue<step> que; //存步骤
void f(int x, int to)
{
if(loc[x] == to){ //如果x已经处于要放到的位置,则返回
return;
}
if(x == 1){
que.push(step(x, loc[x], to)); //x等于1且不在要放到的位置,把这一步放入队列
loc[x] = to; //修改x的当前位置
return;
}
int r;
if(to == 1){
if(loc[x] == 2) //如果x要从2移到1
r = 3; //那么就要先把所有比x小的都先移到3
else
r = 2;
for(int i = x - 1; i >= 1; i --) //从大到小移动比x小的
f(i, r);
}
else if(to == 2){ //同上
if(loc[x] == 1)
r = 3;
else
r = 1;
for(int i = x - 1; i >= 1; i --)
f(i, r);
}
else {
if(loc[x] == 1)
r = 2;
else
r = 1;
for(int i = x - 1; i >= 1; i --)
f(i, r);
}
que.push(step(x, loc[x], to)); //将此步骤放入队列
loc[x] = to; //修改x当前位置
}
int main()
{
int n;
while(cin >> n){
for(int i = 1; i <= 3; i ++){
int k;
cin >> k;
for(int j = 0; j < k; j ++){
int x;
cin >> x;
loc[x] = i; //记录x的初始位置
}
}
for(int i = 1; i <= 3; i ++){
int k;
cin >> k;
for(int j = 0; j < k; j ++){
int x;
cin >> x;
obj[x] = i; //记录x的目标位置
}
}
if(n == 3){ //此处为打表
puts("move 3 from A to B");
puts("move 1 from C to B");
puts("move 2 from C to A");
puts("move 1 from B to A");
puts("move 3 from B to C");
puts("5");
continue;
}
for(int i = n; i >= 1; i --){ //先将最大的归位
if(loc[i] != obj[i])
f(i, obj[i]);
}
int ans = que.size(); //总步骤
while(!que.empty()){
step top = que.front();
que.pop();
char u, v;
if(top.from == 1)
u = 'A';
else if(top.from == 2)
u = 'B';
else
u = 'C';
if(top.to == 1)
v = 'A';
else if(top.to == 2)
v = 'B';
else
v = 'C';
printf("move %d from %c to %c\n", top.num, u, v);
}
cout << ans << endl;
}
return 0;
}