汉诺塔IV
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5949 Accepted Submission(s): 4274
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)
仍然是汉诺塔问题,这次的变形是最大的可以随意移动。
这次的 hanoi 数据记录的是移动到相邻杆子上所需的次数。
1的时候为1,2的时候,需要在1的基础上,把1移动 到最右边,2放到中间,1再移动回来,则:hanoi [ 2 ] = hanoi [ 1 ] + hanoi [ 1 ] * 2 + 1;
……类推一下,得出递推公式:hanoi [ n ] = hanoi [ n – 1 ] * 3 + 1;
然后再考虑题目,可以把最大的移动到小的上面,那么先把上面 n – 1 个移动到中间,再把最大的移动到最右边,再把那 n – 1 个移动到最右边,Game Over~
所以得出结果:ans = hanoi [ n – 1 ] * 2 + 2;
代码如下:
#include <cstdio>
int main()
{
__int64 hanoi[22]; //把n个移到相邻杆子所需次数
hanoi[0] = 0;
hanoi[1] = 1;
for (int i = 2 ; i <= 19 ; i++)
hanoi[i] = hanoi[i-1] * 3 + 1;
int u;
scanf ("%d",&u);
int n;
while (u--)
{
scanf ("%d",&n);
printf ("%d\n",2*hanoi[n-1]+2);
}
return 0;
}