https://ac.nowcoder.com/acm/problem/14585
题意:只能通过移动到相邻位置的汉诺塔问题。
汉诺塔讲解:有三根A,B,C相邻的柱子,A柱子从上到下按递增方式摆放了n个不同大小的圆盘,现在要把A中所有的盘子移动到柱子C上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,盘子只能移动到相邻的柱子上。(比传统汉诺塔多了最后一个限定条件)
具体移动实现方式还是一样用递归的思想:
1:当只有一个圆盘时,移动方式为:A->B,B->C
2:当只有两个圆盘时,移动方式为:把最上面的盘子1移动到B,再把盘子1移动到C。把下面的盘子2移动到B,然后把盘子1移动回到B,再移动回到A,此时就可把2移动到C,最后把盘子1由A移动到B,再由B移动到A即可完成。敲黑板(自己手动模拟一下)
3:......
总结:
1:当只有一个盘子时,由A->B->C。
2:当有n个盘子时,要把1--n-1圆盘从左边移动到右边,再将最下面的圆盘n移动到中间,
把1——n-1圆盘从右边移动到左边,把圆盘n从中间移动到右边,1——n-1圆盘从左边移动到右边。
代码:
void move(char a, char b, char c, int n){ if(n == 0){//递归出口 return; } move(a,b,c,n-1); //把前n - 1块通过b移动到c上 ans++; //把最后一块移动到b上 //printf("%c->%c\n",a,b); move(c, b , a, n - 1); //把n - 1 块通过b移动到a上 ans++; //中间那块移动到c,成功一块 //printf("%c->%c\n",b,c); move(a,b,c,n-1); //继续以上操作 }
当然,虽然n只有26,但这样交个递归函数上去,无疑会超时,那怎么办呢?我们不妨打个表来看看,观察一下n和ans之间有什么关系吧。
n取1~10:
1:2 2:8 3:26 4:80 5:242 6:728 7:2186 8:6560 9:19682 10:59048
不难发现:ans=3^n-1
那么问题ac代码就简单了:
#include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #include<map> #include<queue> using namespace std; typedef long long ll; ll i,j,cnt,n,k,t; ll ans; int main() { while(~scanf("%lld",&n)){ ans=pow(3,n)-1; printf("%lld\n",ans); } }