汉若塔系列续:汉诺塔VIII、汉诺塔IX、汉诺塔X。

汉诺塔VIII,在经典汉若塔问题上。问n个盘子的情况下,移动m次以后,是什么状态。

(与第七代互为逆命题)

我的思路:本质还是dfs,可是用m的值来指引方向,每搜一层确定第i个盘子在哪个塔,o(n)的算法,看图说明:

#include<iostream>
#include<vector>
using namespace std;
char get[65];   //记录I号盘子在哪个塔
long long f[65]; //2^i次的值
void got()   //预处理的f[i]; 注意点:用1<<i会爆int。

{
      f[1]=2;
    for(int i=2;i<65;i++)
      f[i]=f[i-1]*2;
}
void dfs(char fl,char fr,char now,int lev,long long x)  //同汉若塔第七代理。LVE是层数。x是眼下的值
{
    get[lev]=now;
    if(lev==1)return;  //出口
    char temp;
    if(fl==‘A‘&&fr==‘B‘||fl==‘B‘&&fr==‘A‘)temp=‘C‘;
    else if(fl==‘A‘&&fr==‘C‘||fl==‘C‘&&fr==‘A‘)temp=‘B‘;
    else temp=‘A‘;
     lev--;
    long long tx=(f[lev]-1)/2;
    if(x<=tx)                         //小于它的
     {
         if(now==fl)                  //左边的下来
            dfs(fl,temp,fl,lev,x);
         else
            dfs(temp,fr,temp,lev,x);
     }
    else
    {
        if(now==fl)
          dfs(fl,temp,temp,lev,x-tx-1);   //减一,那一步是最以下的塔的移动
        else
          dfs(temp,fr,fr,lev,x-tx-1);
    }
}
int main()
{
    got();
    int T;
    cin>>T;
    while(T--)
    {
       long long n,m;
         cin>>n>>m;
        if(m<=(f[n]-1)/2)
         dfs(‘A‘,‘C‘,‘A‘,n,m);
        else
         dfs(‘A‘,‘C‘,‘C‘,n,m-(f[n]-1)/2);
         vector<int>a,b,c;
        for(int i=n;i>=1;i--)
        {
            if(get[i]==‘A‘)a.push_back(i);
            else if(get[i]==‘B‘)b.push_back(i);
            else c.push_back(i);
        }
        cout<<a.size();
        for(int i=0;i<a.size();i++)
          cout<<" "<<a[i];
        cout<<endl;
         cout<<b.size();
        for(int i=0;i<b.size();i++)
          cout<<" "<<b[i];
        cout<<endl;
         cout<<c.size();
        for(int i=0;i<c.size();i++)
          cout<<" "<<c[i];
        cout<<endl;
    }
    return 0;
}

汉若塔IX hdu2175,经典汉若塔问题上问第M次移动的是几号盘。

思路:同理,第n个盘之前,必先移动前n-1个,再移动第n号,再移动前n-1个,依次。所以二分法查找,在“中间”那个移动的酒在那一个盘了。

#include<iostream>
using namespace std;
long long f[65];  //2^i次的值
void got()       //预处理的f[i]; 注意点:用1<<i会爆int。
{
      f[0]=1;f[1]=2;
    for(int i=2;i<65;i++)
      f[i]=f[i-1]*2;
}
int main()
{
    got();
    long long n,m;
    while(cin>>n>>m&&(n||m))
    {
        while(m!=f[n-1])
        {
            if(m<=f[n-1]-1)
             ;
            else
              m=m-f[n-1];
            n--;
        }
        cout<<n<<endl;
    }
    return 0;
}

汉若塔X  hdu2511  求第m次移动是把几号盘从哪个塔到哪个塔移动。

第九代的扩展。

思路:做到这里,每步的移动已经一清二楚了。还是那颗树,“左中右”遍历序列便是全部状态。因为一共就6种可能移动法。

每次移动后知道下一步的移动。

依然採用二分寻根法。详见代码:

#include<iostream>
#include<string>
using namespace std;
long long f[65];  //2^i次的值
void got()       //预处理的f[i]; 注意点:用1<<i会爆int。

{
      f[0]=1;f[1]=2;
    for(int i=2;i<65;i++)
      f[i]=f[i-1]*2;
}
string getnext(string s,int id)  //状态转移
{
    if(s=="AC")
    {
        if(id==0)return "AB";
        else return "BC";
    }
    else if(s=="AB")
    {
        if(id==0)return "AC";
        else return "CB";
    }
    else if(s=="CB")
    {
        if(id==0)return "CA";
        else return "AB";
    }
     else if(s=="CA")
    {
        if(id==0)return "CB";
        else return "BA";
    }
     else if(s=="BA")
    {
        if(id==0)return "BC";
        else return "CA";
    }
     else if(s=="BC")
    {
        if(id==0)return "BA";
        else return "AC";
    }
}
int main()
{
    got();
    int T;
    cin>>T;
    long long n,m;
    while(T--)
    {
        cin>>n>>m;
        string s="AC";
        while(m!=f[n-1])
        {
            if(m<=f[n-1]-1)
            {
                s=getnext(s,0);
            }
            else
             {
                s=getnext(s,1);
                  m=m-f[n-1];
             }
            n--;
        }
        if(s=="AB")
        cout<<n<<" 1 2"<<endl;
        if(s=="BA")
        cout<<n<<" 2 1"<<endl;
        if(s=="AC")
        cout<<n<<" 1 3"<<endl;
        if(s=="CA")
        cout<<n<<" 3 1"<<endl;
        if(s=="BC")
        cout<<n<<" 2 3"<<endl;
        if(s=="CB")
        cout<<n<<" 3 2"<<endl;
    }
    return 0;
}
时间: 2024-10-10 20:13:22

汉若塔系列续:汉诺塔VIII、汉诺塔IX、汉诺塔X。的相关文章

汉诺塔系列问题

HDU-1207 汉诺塔II 题目链接 https://vjudge.net/problem/HDU-1207 题面 Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘.上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上.并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘.有预言说,这件事完成时宇宙

【分享】初音岛(D.C.)系列(包括D.C.III RX初音岛3) 汉化硬盘版游戏

游戏内容: [040528][CIRCUS]D.C.P.C-ダ?カーポ-プラスコミュニケーション [汉化硬盘版].rar(2.7GB)[060415][CIRCUS]D.C.II 春风のアルティメットバトル! [汉化硬盘版].rar(321.9MB)[060526][CIRCUS]D.C.II-ダ?カーポII- [汉化硬盘版].rar(1.9GB)[061107][CIRCUS]D.C.II -featuring Yun2- [汉化硬盘版].rar(335MB)[070427][CIRCUS]D

汉诺塔系列问题: 汉诺塔II、汉诺塔III、汉诺塔IV、汉诺塔V、汉诺塔VI、汉诺塔VII

汉诺塔II:(hdu1207) /先说汉若塔I(经典汉若塔问题),有三塔,A塔从小到大从上至下放有N个盘子,如今要搬到目标C上, 规则小的必需放在大的上面,每次搬一个,求最小步数.这个问题简单,DP:a[n]=a[n-1]+1+a[n-1],先把 上面的n-1个放在B上,把最大的放在目标C上,再把N-1个放回到C上就可以. </pre><p></p>如今是汉若塔II,改为四个塔,開始方程想简单了,不是最优的.给出网上的一种最优解法例如以下:(1)将x(1<=x&l

算法笔记_013:汉诺塔问题(Java递归法和非递归法)

目录 1 问题描述 2 解决方案  2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus is possible for using animation. e.g. if n = 2 ; A→B ; A→C ; B→C; if n = 3; A→C ; A→B ; C→B ; A→C ; B→A ; B→C ; A→C; 翻译:模拟汉诺塔问题的移动规则:获得奖励的移动方法还是有可能的.

[javascript]模拟汉诺塔

看了博文自己动手写了代码. 这能值几个钱? 请写代码完成汉诺塔的算法:void Hanoi(int maxLevel); 比如2层汉诺塔,需要打印(Console.WriteLine)出如下文本: A -> B A -> C B -> C function HanNuoTa(Level,A,B,C) { if(Level==1) { console.log(A+"-->"+C); } else { HanNuoTa(Level-1,A,C,B); console

递归--练习2--noi6261汉诺塔

递归--练习2--noi6261汉诺塔 一.心得 先把递推公式写出来,会很简单的 二.题目 6261:汉诺塔问题 总时间限制:  1000ms 内存限制:  65536kB 描述 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由64个圆盘构成的塔.目的是将最左边杆上的盘全部移到中间的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面. 这是一个著名的问题,几乎所有的教材上都有这个问题.由于条件是一次只能移动一个盘,且不允许大盘放

关于汉诺塔,C++代码,代码效果演算

 1.故事介绍 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上依照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从以下開始按大小顺序又一次摆放在还有一根柱子上.而且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次仅仅能移动一个圆盘. 2.由来 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在当中一根针

C#中汉诺塔问题的递归解法

百度测试部2015年10月份的面试题之——汉诺塔. 汉诺塔就是将一摞盘子从一个塔转移到另一个塔的游戏,中间有一个用来过度盘子的辅助塔. 百度百科在此. 游戏试玩在此. 用递归的思想解决汉诺塔问题就是分为两种情况: 第一种情况是只有一个盘子的情况,也就是最基本的情况,这种情况下,直接将该盘子从原始塔转移到目标塔即可胜利: 第二种情况是右n个盘子的情况,也就是普遍情况,这种情况下,要将除了最底下的那个盘子以外的(n-1)个盘子从原始塔转移到辅助塔,再把最底下的那个盘子(第n个盘子)从原始塔转移到目标

【数据结构与算法】递归汉诺塔

汉诺塔 汉诺塔是根据一个传说形成的数学问题(关于汉诺塔): 有三根杆子A,B,C.A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小.要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘: 大盘不能叠在小盘上面. 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则. 递归汉诺塔 解题思路: 可以把问题简化成2个盘子的情况,如:A上有两个盘子,B和C是空的.如果要把A的两个盘子全部移动到C,需要经过以下步骤: 1.A移动一个盘子到B 2.A移动一个盘