汉诺塔问题及其变种

1.ABC三个柱子,小的不能在大的上面。从A移到C.

//分析一下可知,每一次想要将一个大盘子从A移到C,就必须先把上面的小盘子从A移到B,最后再把B的盘子移到C,这样就是一个递归的过程。

#include <iostream>

using namespace std;

int num=0;

void hanio(int a,int b,int c,int n){
    if(n<1) return;
    hanio(a,c,b,n-1);
    num++;
    hanio(b,a,c,n-1);
}

int main()
{
    int n;
    cin>>n;num=0;
    hanio(1,2,3,n);
    cout<<num<<endl;
    return 0;
}

当然,直接输出规律也行,答案就是1<<n-1; 2.4个柱子 /* 多了一根柱子而已,但是一看就懵了啊… 是这样的,从A到D的话,设有m个盘子从A到B步数为f[m],那么剩下的n个盘子就服从三个柱子的汉诺塔问题了。最后再从B到D,也是同样的步数。 所以对于n取min(f[m]*2+(1<<(n-m))-1); */

#include <iostream>

using namespace std;
long long  f[101];

int main()
{
    f[1]=1;
    f[2]=3;
    int n;
    cin>>n;
    for(int i=3;i<71;i++){
        f[i]=2*f[1]+(1<<(i-1))-1;
        for(int j=2;j<i;j++){
            f[i]=min(f[i],f[j]*2+(1<<(i-j))-1);
        }
    }
    cout<<f[n]<<endl;
    return 0;
}

3.AC之间不能联通,任何操作都必须经过B.. /* 这个没有上一题难。 第n个盘子从A到C,必须要用到n-1个盘子的结果。 f[n]=f[n-1]+1+f[n-1]+1+f[n-1]=3f[n-1]+2; */

#include <iostream>

using namespace std;
long long  f[101];

int main()
{
    f[1]=2;
    int n;
    cin>>n;
    for(int i=2;i<71;i++){
        f[i]=f[i-1]*3+2;
    }
    cout<<f[n]<<endl;
    return 0;
}

4.在第三题的基础上,允许最大的一个盘子放在小盘子上面。 /* n个盘子从A移动到C等于n-1个盘子从A移动到B,第n个盘子从A到C,n-1个盘子从B到C。 那么f[x]表示x个盘子从A到B。 从A到B和从B到C是一样的步数。 /*

#include <iostream>

using namespace std;
long long  f[101];

int main()
{
    f[1]=1;
    int n;
    cin>>n;
    for(int i=2;i<=n;i++){
        f[i]=3*f[i-1]+1;
    }
    cout<<2*f[n-1]+2<<endl;
    return 0;
}

5.普通汉诺塔问题,问你a个盘子从小到大第b个盘子动了多少下。 /* 最下面的盘子动了1次 第二个动了2次 第三个动了4次….. 总之就是输入a,b,输出 (1<<(a-b)).不写代码了。数据量不大,不需要快速幂。 */ 6. 给n个盘子,大不能压小,问在3根柱子上有多少种摆放方式。 //每个盘子3种,一共3^n

7. 给定每个柱子的各个盘子的大小,求问这种情况可不可能出现。 /* 这道题需要思考。 从最大的开始找。它一定是在A或者在C上。如果在B上面就是错的。 若n在A上面,那么倒数第二大的不是在B上,就是在C上;若n在C上,倒数第二大的不是在A上,就是在B上。 以此类推即可。 可以参考第一题的递归函数,有没有一种返璞归真的感觉? */

#include <iostream>

using namespace std;

int dfs(int k,int a[],int b[],int c[]){
    if(k==b[0]) return 0;
    if(k==a[0]) return dfs(k-1,a+1,c,b);
    if(k==c[0]) return dfs(k-1,b,a,c+1);
    return 1;
}

int main()
{
    int n;
    int a[100],b[100],c[100];
    cin>>n;
    int tem;
    cin>>tem;
    for(int i=0;i<tem;i++)
        cin>>a[i];
    cin>>tem;
    for(int i=0;i<tem;i++)
        cin>>b[i];
    cin>>tem;
    for(int i=0;i<tem;i++)
        cin>>c[i];
    if(dfs(n,a,b,c))
        cout<<"true"<<endl;
    else
        cout<<"false"<<endl;
    return 0;
}
    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/qq_30346729/article/details/72676797
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞