汉诺塔问题

    原创、转载请注明出处。

    题意:经典的汉诺塔问题是有3根柱子,第一根柱子上有n个盘子,下面盘子比上面盘子大,要求把所有盘子移到第三根柱子上,过程中不能使得上面的盘子大于下面的盘子,且每次只能移动一个盘子,问最少需要多少步。

    一开始想的是用普通递归,也就是状态空间搜索路径的方法,这样传的参数比较多。

    在尝试n为比较小的数时想到了用动态规划的方法。

    思路:d(n)为把n个盘子移到另一个柱子上的步数。那么d(n)等于把上面n-1个盘子移到非目标柱子上+把最后一个盘子移到目标柱子上+把非目标柱子上的n-1个盘子移到目标柱子上(这样划分,状态就出来了,是吧),即d(n)=d(n-1)+1+d(n-1)=2*d(n-1)+1。动态规划的状态转移方程,边界条件是盘子为1时移动一步,返回1。

    解释一下,把上面n-1个盘子移动到非目标柱子上相当于把n-1个盘子移动到另一个柱子(即d(n-1)),因为剩下2根柱子没什么区别,把非目标柱子上的n-1个盘子移动到目标柱子上也相当于把n-1个盘子移动到另一个柱子上(即d(n-1)),也是因为剩下2根柱子没什么区别,都可以忽略最大的那个盘子。

    感觉用动态规划的好处就是,有最优子结构,不用考虑具体的步骤。

   (一年没做过动态规划的题了,写的仔细点。。。)

#include<iostream>
using namespace std;

int d(int n)
{
    if(n == 1)
    {
        return 1;
    }
    return (2 * d(n - 1) + 1);
}

int main()
{
    int n;
    while(cin >> n)
    {
        cout << d(n) << endl;
    }
    return 0;
}

   

   

posted @ 2017-11-25 18:07  哲贤  阅读(497)  评论(0编辑  收藏  举报