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
题目分析:又是一道经典汉诺塔的变种,也就是最大的可以放在堆的最上端,而且最左侧不能直接挪到最右侧。所以有两种移动方式,一种是从边侧挪向中间的杆,还有一种是边侧挪向边侧,收先设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 );
    }
}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值