汉诺塔Ⅳ

题目描述

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

Iutput

输入数据的第一行是一个数据T,表示有T组数据。 
每组数据有一个正整数n(1 <= n <= 20),表示有n个盘子。

Output

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

Sample Input



10

Sample Output


19684



方法:首先,你得把他当成一个数学题,摸清他的数学规律。
1.将盘子(或者金片),假设有n片,分为两部分,第一根柱子从上往下共计n-1根为第一部分,最下面一个也是最大的为第二部分。

2.先拿纸笔,自己画总共有1,2,3,4个盘子的情况,先将第一部分从左移到中间,然后将第二部分移至最右边,最后将位于中间的第一部分移至最右边。

3.然后可以得出结论(不犯错的情况下),有两个盘子时,第一部分移到中间需要1步,然后第二部分移至最右边后,第一部分再移至最右边需要2步。这时可以猜测:是不是第一部分从左边移至中间的步数和从中间移至最右边的步数相等。然后计算有三个盘子时,发现上面两个盘子移至中间需要四步,从中间移至最右边也是四步,再计算更多,你会发现猜测是正确的。
4.然后你还可以得出一个规律,将n个第一部分的盘子移至最右边需要的步数,是将n-1个盘子移至最右边的三倍加二。
5.C语言编程实现



#include <stdio.h>
int main()
{
   int N =21;
    int ac[N],ac_=2,b[N];
    ac[1]=0;
    int i,j,k=1,a;
    scanf("%d",&i);//执行次数
    while(k<=i)
    {
        scanf("%d",&j);//盘子数
        for(a=2;a<=j;a++)
        {
            ac[a]=3*ac[a-1]+2;//第一部分从A柱到C柱的步数
        }
        b[k]=ac[j]+2;//第一部分加第二部分的移动步数
        k++;
    }
    int c;
  for(c=1;c<k;c++)//打印所有情况
  {
      printf("%d",b[c]);
      if(c!=k-1)

          printf("\n");//为了提交成功,最后一个数字后面不能有回车

  }
  return 0;



}


借鉴:https://blog.csdn.net/HYH863677698/article/details/79252063
posted on 2018-10-11 16:49  Zlc527  阅读(261)  评论(0)    收藏  举报