汉诺塔问题

汉诺塔


问题链接: https://www.jisuanke.com/course/2291/182230

问题分析:

参考博客:http://www.cnblogs.com/xxNote/p/3965739.html

  • 先把n-1个盘子从A移动到B,剩下最大的那个盘子在A(这时所移动的次数为 f (n-1)
  • 再将最大的那个盘子移到C盘,(这时所移动的次数为 f (n-1) + 1
  • 最后将那n-1个盘子从B移到C盘上,所移动的次数为 f (n-1) + 1 + f (n-1)  )
  • 递推公式:f (n) = f ( n - 1) * 2 + 1
  • 通项公式:f (n) = 2 ^ n - 1
  • long long 类型 或者 __int64

 源代码

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <stdint.h>

using namespace std;
long long step = 0;
long long t = 0;

long long f(long long n)    //计算所消耗的体力
{
    if(n == 1)
        return 1;
    else
        return f(n-1)*2+n;
}
long long hanoi(long long n)
{
    if(n == 1)
        return 1;
    else
        return hanoi(n-1)*2+1;
}



int main()
{
    long long n;
    scanf("%lld", &n);
    printf("%lld %lld\n", hanoi(n), f(n));
    return 0;
}


 汉诺塔III       hdu 2064

问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2064

问题分析:

  • 将n-1个盘子从A ----> C, 移动 a [n-1] 
  • 第n个盘子从A  ----> B, 移动 1 
  • n-1个盘子再从 C  ----> A, 移动 a [n-1] 
  • 第n个盘子从 B ----> C,移动 1
  • 最后n-1个盘子从 A ----> C,移动 a [n-1] 
  • 总共移动 3*a[n-1] + 2

源代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;

long long a[50];

int main()
{
    a[0] = 0;
    for(int i = 1; i <= 35; i++)
        a[i] = 3*a[i-1]+2;
    int n;
    while(scanf("%d", &n) != EOF)
        printf("%lld\n", a[n]);
    return 0;
}

 



汉诺塔VI  hdu 1996

问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1996

问题分析:

  • 类似于高中的5封信投到3个信箱中,共有3^5中投法
  • 此题为n个盘子放到3个柱子上,所以共有3^n种
  • 使用快速幂
  • 快速幂模板
    // a的b次方
    int pow(int a, int b) 
    {
        int ans = 1, base = a;
        while (b != 0) 
        {
            if (b & 1)
                ans *= base;
            base *= base;
            b >>= 1;
        }
        return ans;
    }

     

源代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;

long long fast(long long x, long long n)        //快速幂
{
    long long res = 1;
    while(n>0)
    {
        if(n&1)
            res= res*x;
        x = x*x;
        n >>= 1;
    }
    return res;
}

int main()
{
    long long t;
    scanf("%lld", &t);
    while(t--)
    {
        long long n;
        scanf("%lld", &n);
        long long sum = fast(3, n);
        printf("%lld\n", sum);
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值