这个题不同的是开始状态不规则,目标状态也不规则
我们这里有个折中的方法,就是从开始和目标两个状态同时向一个参考状态移动。
我们分析这个问题,会发现我们必须先把最大的圆盘放到目标位置,所以目前位置s和目标位置p上都不能存在其他比当前圆盘小的圆盘,然后把最大的圆盘从s移动到p上,
所以ans等于把其他的圆盘从s移动到中转位置的步骤数step1加上把其他的圆盘从p移动到中转位置的步骤数step2再加上1
所以ans = step1+step2+1;
其他的移动方式和经典的汉诺塔差不多了,
不过我们发现总共3个位置,
要想把其他的圆盘移动到中转位置上,s和p位置上除了当前圆盘外都是空的,那么中转位置上肯定是有序的,从上倒下圆盘半径依次减小。
所以我们把其他的小圆盘再从中转位置移动到目的位置,那么步骤数就和经典汉诺塔一样了。
即有n个盘子需要移动的话,就需要2^(n-1)-1次移动。
在加上中间把当前圆盘移动一次。
所以把小圆盘移动都中转圆盘后只需2^(n-1)次移动就能实现把所有比当前圆盘小的圆盘移动到墓地位置了
代码如下;
#include <cstdio> #define M 70 int start[M], targe[M]; long long f(int *p, int k, int fina) { if(k==0) return 0; if(p[k]==fina) return f(p,k-1,fina); return f(p,k-1,6-fina-p[k])+(1LL<<(k-1)); } int main () { long long ans; int n, cas = 0; while(scanf("%d",&n), n) { for(int i = 1; i <= n; i++) scanf("%d",&start[i]); for(int i = 1; i <= n; i++) scanf("%d",&targe[i]); int c = n; for(;c>=1&&start[c]==targe[c];c--); printf("Case %d: ",++cas); if(c==0) {printf("0\n"); continue;} int other = 6 - start[c] - targe[c]; ans = f(start,c-1,other)+f(targe,c-1,other)+1; printf("%lld\n",ans); } return 0; }