• 【ACwing 96】奇怪的汉诺塔——区间dp


    (题面来自ACwing)

    汉诺塔问题,条件如下:

    1、这里有A、B、C和D四座塔。

    2、这里有n个圆盘,n的数量是恒定的。

    3、每个圆盘的尺寸都不相同。

    4、所有的圆盘在开始时都堆叠在塔A上,且圆盘尺寸从塔顶到塔底逐渐增大。

    5、我们需要将所有的圆盘都从塔A转移到塔D上。

    6、每次可以移动一个圆盘,当塔为空塔或者塔顶圆盘尺寸大于被移动圆盘时,可将圆盘移至这座塔上。

    请你求出将所有圆盘从塔A移动到塔D,所需的最小移动次数是多少。

    输入格式

    没有输入

    输出格式

    对于每一个整数n(1n12),输出一个满足条件的最小移动次数,每个结果占一行。

      三个柱子的汉诺塔问题最小步数存在通项公式:2^n - 1,其中n为圆盘数。这个式子很容易由首项a_1 = 1和递推公式a_n = a_(n-1) * 2 + 1得到。递推式的含义是,先利用2个柱子把上面的n-1个圆盘移到B柱上,把第n个圆盘移到C上,再把B柱上的n-1个移到C上。

      四个柱子的汉诺塔问题并不是简单的逐项递推,需要在转移时做出决策。设g[n]为n盘3柱问题的最短步数,f[n]为n盘4柱问题的最短步数,状态转移方程:

       f[i] = min(f[i - j] * 2 + g[j])

       其中j属于[1, i)。这个式子的含义是,我们选择上面的i - j个圆盘,在4柱模式下把它们移到B柱上,然后用其余的3个柱子把剩下的i个圆盘移到D柱上,最后把B柱上的圆盘在4柱模式下移到D柱上。

    代码:

    1. #include <cstdio>  
    2. #include <cstring>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int g[20], f[20], ans;  
    6. int main() {  
    7.     for (int i = 1; i <= 12; ++i)  
    8.         g[i] = (1 << i) - 1;  
    9.     puts("1");  //特判1个圆盘
    10.     memset(f, 0x3f, sizeof(f));  
    11.     f[1] = 1;  
    12.     for (int i = 2; i <= 12; ++i) {  
    13.         for (int j = 1; j < i; ++j)  
    14.             f[i] = min(f[i], 2 * f[j] + g[i - j]);  
    15.         printf("%d ", f[i]);  
    16.     }  
    17.     return 0;  
    18. }  
  • 相关阅读:
    vmware 连网问题
    js控制表单非法输入时提交
    简单的jsp&servlet 购物车项目
    html引入css不显示问题
    每天学点java_反射作用
    java选择特定的值2--抽象enum
    java选择特定的值
    1 小时 SQL 极速入门(一)
    460004600146002MNCMCCIMSI
    网络中存在2台DHCP服务器问题
  • 原文地址:https://www.cnblogs.com/TY02/p/11255855.html
Copyright © 2020-2023  润新知