汉诺塔,经典的递归问题,我们考虑每个盘子的初态和末态,对于一个盘子的移动限制就是大的不能放在小的上,那么我们肯定是先选择移动大的,那么如何移动?假设我们将一个大的从A移动到C,那么我们一定是把A上的小的和C上的小的移动到B,否则无法移动,这样我们就找到了一种移动方法,从大到小移动,这样移动一定是最少的,因为每一步的移动都是必要的,缺失一步移动大盘子都无法移动。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1005
int n,a[maxn],b[maxn],tot;
char s[5];
void solve(int x,int fr,int to)
{
if (fr==to) return;
int res=6-fr-to;
for (int i=x-1;i>=1;i--)
if (a[i]!=res) solve(i,a[i],res);
a[x]=to;
tot++;
printf("move %d from %c to %c\n",x,s[fr],s[to]);
}
int main()
{
scanf("%d",&n);
s[1]='A';s[2]='B';s[3]='C';
for (int i=1;i<=3;i++)
{
int k,w;
scanf("%d",&k);
for (int j=1;j<=k;j++)
{
scanf("%d",&w);
a[w]=i;
}
}
for (int i=1;i<=3;i++)
{
int k,w;
scanf("%d",&k);
for (int j=1;j<=k;j++)
{
scanf("%d",&w);
b[w]=i;
}
}
for (int i=n;i>=1;i--) solve(i,a[i],b[i]);
printf("%d\n",tot);
return 0;
}