Menu
0 Comments

初识汉诺塔问题 – supervsky

汉诺塔

汉诺塔(Tower of 河内)根源在于印度传统,当梵天杜撰了全局的,它修建了三个金柱。,一柱从共计到顶部桩有64个金盘。。梵定命令Brahman从上面重行位圆盘并把它放在阄石头上。。并常客,圆盘不克不及在小圆盘上缩小。,你总算却在三个柱子正中的一次自负的任一圆盘。。

——引自维基百科

若给汉诺塔传统中三根柱子识别用英文字母a,b,C命名,不料一列没有经验的N盘(1)<=n<=100000), 若要把a柱子上的所有圆盘转移到c柱子上,问最少需要自负的多少次圆盘。

自负的磁盘的常客列举如下:

  1. 一次总算却自负的任一磁盘
  2. 大直径圆盘必不可少的事物放在小圆盘上。

隐现求解

汉诺塔成绩经过简略的隐现举行求解,指定遗传密码更简约,通俗易懂。竟汉诺塔成绩的自负的次数是有规定可寻的,用隐现指定遗传密码查找有关的常客,并经过算学办法开腰槽总算功效才是至高的的。

  • 当n=1时,A列不料任一磁盘,立即的自负的到C列
  • 当n>1时,依据常客1和2,将列N-1磁盘自负的到B列,和将剩的磁盘移到C,和将暂时没有经验的在B上的N-1盘自负的到C。

隐现解究竟是压低PR的衡量的进程。,何苦经过自负的N-1盘O来反复上述的两点。。C指定遗传密码的隐现解如图3-1所示。

void Hanoi(int n, char a, char b, char c)
{
    if(n == 1)
    {
        自负的(A), c);
    }
    else
    {
        河内(N)-1, a, c, b); /*将列N-1磁盘自负的到B列*/
        自负的(A), c);      自负的A到C的差数磁盘正中鹄的任一
        河内(N)-1, b, a, c); 和将暂时没有经验的在B上的N-1盘自负的到C。
    }
}

void Move(char a, char b)
{
    printf("Move 1 disk: %c ---------> %c\n", a, b);
}

图3-1    汉诺塔隐现求解指定遗传密码

如图3-1的指定遗传密码可以得到汉诺塔自负的圆盘次数的递推相干:

  • 河内(N)) = 1 , n =1 ;
  • 河内(N)) = 2 * 河内(N)-1) + 1, n>1;

令b(n) = 河内(N))+1,可以得到推论,B(n)是2的碱。,公比为2的生长。很就可以开腰槽,

b(n) = 2n, n>0

河内(N)) = 2n – 1, n>0


加强约束条件的汉诺塔

Q: 即使添加了限度局限,圆盘总算却在邻近的柱正中的自负的。,多少处置?认为A, b, 并排C,正中的的B,即a, C不邻近,在A到C上自负的磁盘必不可少的事物率先自负的到B。,和自负的到C。

From TOJ 3270 Strange Hanoi Tower

运用隐现处置同一的深思,依据原型常客和新的约束条件,自负的圆盘数的导出规定。

  • 当n=1时,A列不料任一磁盘,搬到B先,再次自负的到C
  • 当n>1时,A柱的N-1盘率先经过B CO自负的到C列。,将A列中剩的任一盘移到B 和将C柱的N-1圆盘自负的到B柱上。 和B列的仅仅磁盘自负的到C,鞋楦,A列的N-1盘经过B移到C。

隐现指定遗传密码如图3-2所示。

void Hanoi(int n, char a, char b, char c)
{
    if(n==1)
    {              //A列不料任一磁盘,搬到B先,再次自负的到C
        自负的(A), b);
        自负的(B), c);
    }
    else
    {
        河内(N)-1, a, b, c); //A柱的N-1盘率先经过B CO自负的到C列。
        自负的(A), b);          A列剩的任一磁盘移到B
        河内(N)-1, c, b, a) 将C柱的N-1圆盘自负的到B柱上
        自负的(B), c);          将B列的仅仅磁盘自负的到C
        河内(N)-1, a, b ,c); 将A的N-1磁盘经过B自负的到C
    }
}
void Move(char a, char b)
{
        printf("%c --> %c\n", a, b);
}

 图3-2    加强约束条件的汉诺塔隐现指定遗传密码

从图3-2买到,盘数与盘数正中的的递推相干,

  • 当n=1时,河内(N)) = 2;
  • 当n>1时,河内(N)) = 3 * 河内(N)-1) + 2;

竟开腰槽:

河内(N)) = 3n – 1, n>0

左右基本图案的总算能够绝大。,出口总算 谋划抵御1,000,000,007。

高阶整体取幂模块

因而toJ 3270将此基本图案替换为(3)n – 1) % 1000000007道算学题。对高阶整体取幂模块运算,可经过功率去除来处置。前进的指定遗传密码如图3-3所示。。

#include 
constlonglong p = 1000000007;

longlong power(longlong x, longlong n)
{//
    if( n == 0)
        return1;
    elseif(n == 1)
        return x;
    else
    {
        longlong tmp = 功率(X), n/2);
        if( n % 2 == 1)
            return tmp * tmp * x % p;  // 若 n 为奇,3n = 3 * 3n/2 * 3n/2elsereturn tmp * tmp % p;      // 若 n 为偶,3n = 3n/2 * 3n/2    }
}

int main()
{
    longlong n;
    while(斯坎夫"%lld", &n) && n)
    {
        printf("%lld\n", power(3, n)-1);
    }
    return0;
}

图3-3    TOJ 3270 Strange Hanoi 塔式涉及码

深思:你为什么开腰槽总算?

在无论哪个等比级数中,无论哪个素数都可以增加1。,左右条的幂数的是1减去素数的任一并发症。。

—— 费马

有兴趣的朗读者可以看见熟练手法费马定理。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注