分析:

我们把汉诺塔变换看为是路径的变换,这样我们只要能把路径的变换调整就能知道总步骤
eg:
a->c步数 我们用数组hnt[1][3]表示
a->b步数 我们用数组hnt[1][2]表示
b->a步数 我们用数组hnt[2][1]表示
b->c步数 我们用数组hnt[2][3]表示
c->a步数 我们用数组hnt[3][1]表示
c->b步数 我们用数组hnt[3][2]表示
如果 我现在要调整将位置b,与位置c进行交换(a,b,c)->(a,c,b)
那么我们只需调整他们之间的位置
f(a,b,c):
swap(hnt[a][c],hnt[a][b]);
swap(hnt[b][a],hnt[c][a]);
swap(hnt[b][c],hnt[c][b]);
这样所有的步数就都调整过来了
同理 现在要调整将位置a,与位置c进行交换(a,b,c)->(b,a,c)
f(a,b,c) 换成f(c,a,b)就行了

减少复杂度

我们用递归会超时,复杂度太大O(2^N)
所以我们转变思路,将递归变为递推
通过位置关系,
我们可以知道下一层就是本层位置变换2次步数之和(一个是位置a,与位置c进行交换,一个是位置b,与位置c进行交换)+a->c这一步
这样我们的复杂度就会变为O(N)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ll long long
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
const int maxx=1e6;
ll hnt[5][5],bb[5][5];//hnt汉诺塔数组,bb是保留上一次的汉诺塔数组
ll n,m;
void nf(ll (&p)[5][5],ll a,ll b,ll c)
{
    swap(p[a][c],p[a][b]);
    swap(p[b][a],p[c][a]);
    swap(p[b][c],p[c][b]);
}//交换p[][]中的b<->c      原本a,b,c 交换后a,c,b

void nnf(ll a,ll b,ll c)//让上一次(n-1)层汉诺塔数组  进行交换
{
    for(ll i=1;i<=3;i++)
    {
        for(ll j=1;j<=3;j++)
        {
            bb[i][j]=hnt[i][j];//让bb数组看为是原数组(n-1,a,b,c)
        }
    }
    nf(hnt,a,b,c);//hnt 交换b<->c 即步数(n-1,a,c,b)
    nf(bb,c,a,b);//bb 交换a<->b 即步数(n-1,b,a,c)
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            hnt[i][j]+=bb[i][j];//步数(n-1,a,c,b)(n-1,b,a,c)二者相加
        }
    }
}
void ff(ll n,ll a,ll b,ll c)//递推实现汉诺塔 步数统计
{
    for(ll i=1;i<=n;i++)
    {
        nnf(a,b,c);
        hnt[1][3]++;//最后加上a->c 这一步
    }
}
ll poww(ll x,ll y)
{
    ll ans=1;
    while(y)
    {
            if(y&1)
        {
            ans*=x;
        }
        x*=x;
        y>>=1;
    }
    return ans;
}//快速幂算总步数
int main(int argc, char** argv) 
{
    cin >> n;
    ff(n,1,2,3);
    ll sum=poww(2,n)-1;
    printf("A->B:%lld\n",hnt[1][2]);
    printf("A->C:%lld\n",hnt[1][3]);
    printf("B->A:%lld\n",hnt[2][1]);
    printf("B->C:%lld\n",hnt[2][3]);
    printf("C->A:%lld\n",hnt[3][1]);
    printf("C->B:%lld\n",hnt[3][2]);
    printf("SUM:%lld\n",sum);
    return 0;
}