zoukankan      html  css  js  c++  java
  • HDOJ2175 汉诺塔IX

    题目大意:基于汉诺塔原型,第一根柱子上有n个盘子,从上至下编号从1依次递增至n。在最佳移动方案中,第m次所移动的盘子的编号。

    解题思路:模拟必然是会超时的。但根据汉诺塔的递归原理,容易发现,对于n阶汉诺塔,将第一个盘从A柱移动到B柱是一步,将前两个盘从A柱移动到B柱是3步,以此类推,将n个盘从A柱移动到B柱的步数是2^n-1步。而第m步必然在以上递推的值所划分出来的区间之中。查找到区间i后,可以发现,我们把问题缩小为求n-i阶汉诺塔的第m-(used[i]+1)步。同时,如果发现第m步正好是i阶汉诺塔移动后的下一步,那必然是移动i+1号盘子,若正好是i阶汉诺塔移动的步数,那就必然是1号盘子,这就是递归的边界了。

    每一阶所需的步数可以用公式快速得出并预缓存,相对于模拟,这种区间查找,缩小范围的方法极大地降低了时间复杂度。

     1 #include <iostream>
     2 using namespace std;
     3 long long int cache[66];
     4 int flag=1;
     5 void find(long long int m)
     6 {
     7     int i;
     8     for(i=1;i<=65;i++)
     9     {
    10         if(cache[i]==m)
    11         {
    12             flag=1;
    13             return;
    14         }
    15         if(cache[i]<m&&m<cache[i+1])
    16         {
    17             if((cache[i]+1)==m)
    18             {
    19                 flag=i+1;
    20                 return;
    21             }
    22             else
    23             {
    24                 find(m-(cache[i]+1));
    25             }
    26         }
    27     }
    28 }
    29 int main() {
    30     int i;
    31     cache[1]=1;
    32     for(i=2;i<=65;i++)
    33     {
    34         cache[i]=cache[i-1]*2+1;
    35     }
    36     long long int n,m;
    37     while(cin>>n>>m)
    38     {
    39         if(n==0&&m==0)
    40             break;
    41         flag=1;
    42         find(m);
    43         cout<<flag<<endl;
    44     }
    45         return 0;
    46 }
  • 相关阅读:
    使用NPOI将TABLE内容导出到EXCEL
    如何判断一个指定的经纬度点是否落在一个多边形区域内?
    SQL随记(三)
    SQL随记(二)
    SQL随记(一)
    微信开发(1)
    关于面试经验的总结
    动态代理是什么
    集合的遍历以及在Spring中的注入
    向服务器发送邮件(四)
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/5322452.html
Copyright © 2011-2022 走看看