汉诺塔问题

汉诺塔问题

汉诺塔I

有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘; 大盘不能叠在小盘上面。 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。问:如何移?最少要移动多少次?
思路:递推式:f(i)=2*f(i-1)+1;

  • 将上面的n-1个通过b从a移动c
  • 将第n个移到c
  • 将n-1个通过a从b移动到c

HDUOJ 1027 诺汉塔II

思路:递推式:f(i)=min(2*f(n-r)+2^r-1),1<=r<i;

  • 将上面n-r个圆盘通过c,d移动到b
  • 将剩余r个使用三柱法移动到d,即2^r-1
  • 将n-r通过a,c移动到d
  • 上述求出r的所有取值的最小值为最终解

HDUOJ 2064 汉诺塔III

思路:递推式:f(i)=3*f(i-1)+2

  • 首先将i-1个圆盘移动到最右边的柱子
  • 第i个圆盘移动到中间
  • 前i-1个圆盘移动到最左边
  • 第i个圆盘移动到最右边
  • 最后将i-1个圆盘移动到最右边

HDUOJ 2077 汉诺塔IV

思路1:

  • 设a[i]为将i块圆盘从最左边移动到最右边
  • b[i]为将i个圆盘移动到相邻的柱子(移动到相邻的柱子步数相同)
  • c[i]为本题的步数

求c[n]:

  • 将n-1个圆盘移动到中间柱子
  • 将第n个圆盘(最大的圆盘)移动到最右边
  • 将中间n-1个圆盘移动到最右边

c[n]=2*b[n-1]+2;

求b[n]:

  • 先将n-1个移动到最右边
  • 再将第n个移动到中间
  • 最后将n-1个从右边移动到中间

b[n]=a[n-1]+b[n-1]+1;

思路2:递推式:f(n)=3*f(n-2)+4;

  • 先把n-2个盘子从A通过B移动到C,f(n-2)
  • 在把第n-1和第n个盘子从A移动到B,大盘在上,2步
  • 再把n-2个盘子从C通过B移动到A,f(n-2)
  • 再把第n-1和第n个盘子从B移动到C,2步
  • 最后将n-2个盘子从A通过B移动到C,f(n-2)

HDUOJ 1997 汉诺塔VII

思路:

若把n个盘子从A通过B移动到C,则先把n-1个盘子从A移动到B,再把第n个盘子从A移动到C,再把n-1个盘子从B移动到A

所以只需要判断序列是否符合把n个盘子从A移动到C,第n个只能出现在A的底部,或柱子C的底部,否则序列错误

当第n个盘子在A的底部,则继续判断剩下的序列是否把n-1个盘子从A移动到B

当第n个怕你在C的底部,则继续判断剩下的序列是否把n-1个盘子从B移动到C

#include <iostream>
using namespace std;

const int MAX = 65;
int a[MAX], b[MAX], c[MAX];

bool judge(int n, int st[], int ed[], int zh[])
{
    if(zh[0]==n) return 0;
    else if(st[0]==n) return judge(n-1, st+1, zh, ed);
    else if(ed[0]==n) return judge(n-1, zh, ed+1, st);
    return 1;
}
int main()
{
    int T, N, m, p, q;
    cin >> T;
    while(T--)
    {
        cin >> N;
        cin >> m;
        for(int i=0; i<m; i++)
            cin >> a[i];
        cin >> p;
        for(int i=0; i<p; i++)
            cin >> b[i];
        cin >> q;
        for(int i=0; i<q; i++)
            cin >> c[i];
        a[m] = b[p] = c[q] = -1;
        if(judge(N, a, c, b)) cout << "true" << endl;
        else                  cout << "false" << endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值