汉诺塔问题及其变种

来源:互联网 发布:nginx 80端口无法访问 编辑:程序博客网 时间:2024/04/29 18:57


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;}


原创粉丝点击