题目大意:给你一个最初状态的汉诺塔,再给你一个最终状态的汉诺塔,问至少需要移动多少步,才能使最初状态变成最终状态
解题思路:从最大的盘子开始找,找到第一个在不同柱子上的最大的盘子k,比这个盘子大的盘子就不需要考虑了,因为不用移动到他们.
如果要将找到的这个最大的盘子k移动到相应的柱子的话,要移动过去的最终状态就是三根柱子:
最大盘子k的那根柱子只有一个盘子,就是那个最大盘子k,要移动过去的柱子是空的,剩下的一根柱子是放着k-1个盘子的
现在设置一个函数统计需要移动的次数,函数有三个参数:状态数组,要移动的盘子,要移动到哪根柱子
因为移动是对称的,所以最终的结果就是:初始态移动成一种状态 + 最终态移动成相应的状态,具体看代码,好难解释
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100
int start[maxn], end[maxn];
long long move(int *temp, int num, int Final) {
if(num == 0)
return 0;
if(temp[num] == Final)
return move(temp, num - 1, Final);
return move(temp,num-1,6-temp[num]-Final) + (1LL << ( num - 1));
}
int main() {
int N, mark = 1;
while(scanf("%d",&N) == 1 && N) {
for(int i = 1; i <= N; i++)
scanf("%d",&start[i]);
for(int i = 1; i <= N; i++)
scanf("%d",&end[i]);
int MAX = N;
while(MAX >= 1 && start[MAX] == end[MAX])
MAX--;
long long ans = 0;
if(MAX >= 1) {
int Final = 6 - start[MAX] - end[MAX];
ans = move(start,MAX-1,Final) + move(end,MAX-1,Final) + 1;
}
printf("Case %d: %lld\n",mark++, ans);
}
return 0;
}