hdu 2077 汉诺塔IV(推公式+dp)

汉诺塔IV

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4635    Accepted Submission(s): 3397

Problem Description 还记得汉诺塔III吗?他的规则是这样的:不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到小盘的上面。xhd在想如果我们允许最大的盘子放到最上面会怎么样呢?(只允许最大的放在最上面)当然最后需要的结果是盘子从小到大排在最右边。

 

Input 输入数据的第一行是一个数据T,表示有T组数据。

每组数据有一个正整数n(1 <= n <= 20),表示有n个盘子。

 

Output 对于每组输入数据,最少需要的摆放次数。

 

Sample Input

2 1 10  

Sample Output

2 19684  

Author xhd  

Source
ACM程序设计期末考试_热身赛(感谢 xhd & 8600) 题目分析:又是一道经典汉诺塔的变种,也就是最大的可以放在堆的最上端,而且最左侧不能直接挪到最右侧。所以有两种移动方式,一种是从边侧挪向中间的杆,还有一种是边侧挪向边侧,收先设g(x)为x个盘子从中间和边侧中间挪动需要的步数,那么还是利用子问题的考虑方法,先将n-1个盘子挪到最右侧,然后将大盘子挪到中间,再将n-1个盘子挪到中间,这样任务就完成了,得到g(n) = 3*g(n-1)+2,那么下面我们再看f(n),也就是将n个盘子从最左侧挪到最右侧需要的步数,首先将n-1个挪到中间,然后最大的盘子挪到中间再挪到最右侧,然后n-1个盘子也挪到最右侧,得到f(n) = 2*g(n-1)+2,那么此题得解

代码真是简单的幼儿园小孩都1A啊

#include <cstdio>
#define MAX 22

using namespace std;

typedef long long LL;

int t,n;
LL f[MAX],g[MAX];

int main ( )
{
    g[1] = 1 , g[0] = 0 , f[1] = 2;
    for ( int i = 2 ; i < MAX ; i++ )
        g[i] = 3*g[i-1] + 1;
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d" , &n );
        printf ( "%lld\n" , 2*g[n-1]+2 );
    }
}

 

    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/qq_24451605/article/details/44657107
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞