题目描述

古老的汉诺塔问题是这样的:用最少的步数将N个半径互不相等的圆盘从1号柱利用2号柱全部移动到3号柱,在移动的过程中小盘要始终在大盘的上面。

  现在再加上一个条件:不允许直接把盘从1号柱移动到3号柱,也不允许直接把盘从3号柱移动到1号柱。

  把盘按半径从小到大用1到N编号。每种状态用N个整数表示,第i个整数表示i号盘所在的柱的编号。则N=2时的移动方案为:

  (1,1)=>(2,1)=>(3,1)=>(3,2)=>(2,2)=>(1,2)=>(1,3)=>(2,3)=>(3,3)

  初始状态为第0步,编程求在某步数时的状态。

输入

 输入文件的第一行为整数T(1<=T<=50000),表示输入数据的组数。

  接下来T行,每行有两个整数N,M(1<=n<=19,0<=M<=移动N个圆盘所需的步数)。

输出

输出文件有T行。

  对于每组输入数据,输出N个整数表示移动N个盘在M步时的状态,每两个数之间用一个空格隔开,行首和行末不要有多余的空格。

个人想法

嗯。。。网络有点卡,不太好讲那么复杂的东西。

[怒火中烧]*1000000000000…000000:你到底讲不讲?

讲讲讲,不然我写这干哈

方法1

先设置f[i],表示i个圆盘全部从第1个柱子到第3个柱子需要的步数。

蒟蒻找规律

f[1]=2 f[2]=8 f[3]=26

好,于是乎——

f[i]=f[i-1]*3+2

再设s[i]为当前状态下第i个圆盘所在的位置。

我们再从f[n]到f[1]暴力判断是否成立,成立再改变s[i]值,最后输出就好了

方法2

————大打表之术————

将答案一个个copy下来,使用条件判断语句,AC

预计时间复杂度:O(1)

#include<cstdio>
#include<cstring>
using namespace std;
int t,i,n,m,j,k,q,f[20],s[20],l;
bool bz[20];
int main()
{
scanf("%d",&q);
for (i=1;i<=q;++i)
{
scanf("%d%d",&n,&m);
t=0;
memset(f,0,sizeof(f));
while (f[t]<m)
{
t++;
f[t]=f[t-1]*3+2;
}
memset(bz,0,sizeof(bz));
l=t-1;
if (t==0)
{
for (j=1;j<=n;j++)
{
printf("%d%c",1,' ');
}
printf("\n");
} else
{
if (f[t]==m)
{
for (j=1;j<=t;j++)
{
printf("%d%c",3,' ');
}
for (j=t+1;j<=n;j++)
{
printf("%d%c",1,' ');
}
printf("\n");
}else
{
for (j=1;j<=n;j++)
s[j]=1;
t=0;
for (j=l;j>=1;--j)
{
if (t+f[j]+1<=m)
{
t+=f[j]+1;
for (k=1;k<=j;k++)
{
if (bz[j]==0)
{
s[k]=3;
bz[k]=1;
}else
{
s[k]=1;
bz[k]=0;
}
}
if (bz[j+1]==1) s[j+1]-=1;else s[j+1]+=1;
if (s[j+1]==3) bz[j+1]=1;
if (s[j+1]==1) bz[j+1]=0;
j++;
}
}
while (t<m)
{
t++;
if (bz[1]==0) s[1]++;else s[1]--;
if (s[1]==n) bz[1]=1;
if (s[1]==1) bz[1]=0;
}
for (j=1;j<=n;j++)
{
printf("%d%c",s[j],' ');
}
printf("\n");
} }
}
}

【GDKOI2004】汉诺塔的更多相关文章

  1. JZOJ 2136. 【GDKOI2004】汉诺塔

    2136. [GDKOI2004]汉诺塔 (Standard IO) Time Limits: 3000 ms  Memory Limits: 128000 KB  Detailed Limits   ...

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

    目录 1 问题描述 2 解决方案  2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...

  3. C#递归解决汉诺塔问题(Hanoi)

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace MyExamp ...

  4. 数据结构0103汉诺塔&八皇后

    主要是从汉诺塔及八皇后问题体会递归算法. 汉诺塔: #include <stdio.h> void move(int n, char x,char y, char z){ if(1==n) ...

  5. Conquer and Divide经典例子之汉诺塔问题

    递归是许多经典算法的backbone, 是一种常用的高效的编程策略.简单的几行代码就能把一团遭的问题迎刃而解.这篇博客主要通过解决汉诺塔问题来理解递归的精髓. 汉诺塔问题简介: 在印度,有这么一个古老 ...

  6. 几年前做家教写的C教程(之四专讲了指针与汉诺塔问题)

    C语言学习宝典(4) 指针:可以有效的表示复杂的数据结构,能动态的分配动态空间,方便的使用字符串,有效的使用数组,能直接处理内存单元 不掌握指针就没有掌握C语言的精华 地址:系统为每一个变量分配一个内 ...

  7. python实现汉诺塔

    经典递归算法汉诺塔分析: 当A柱子只有1个盘子,直接A --> C 当A柱子上有3个盘子,A上第一个盘子 --> B, A上最后一个盘子 --> C, B上所有盘子(1个) --&g ...

  8. fzu1036四塔问题(汉诺塔问题拓展)

    #include<iostream> #include<cstdio> #include<cmath> using namespace std; ]; int ru ...

  9. 1019: [SHOI2008]汉诺塔

    1019: [SHOI2008]汉诺塔 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1495  Solved: 916[Submit][Status] ...

随机推荐

  1. 2018-04-19:innodb和myisam区别

    福哥答案2020-04-19:

  2. C#LeetCode刷题之#448-找到所有数组中消失的数字(Find All Numbers Disappeared in an Array)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3712 访问. 给定一个范围在  1 ≤ a[i] ≤ n ( n ...

  3. 极简 Node.js 入门 - 2.2 事件

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  4. ASP.NET Core 奇技淫巧之接口代理转发

    前言 先讲讲本文的开发背景吧.. 在如今前后端分离的大背景下,咱的客户又有要求啦~ 要前后端分离~ 然因为种种原因..没办法用用纯前端的框架(其实是学习成本高,又没钱请前端开发人员)... 所以最终决 ...

  5. PYTHON-anaconda-安装

    1.下载: 官网地址:https://www.anaconda.com/products/individual/get-started 镜像地址(推荐):https://mirrors.tuna.ts ...

  6. Html5与CSS3(选择器)

    <!-- 作者:offline 时间:2018-03-21 描述:1.全选择器 *{属性1:属性值2:属性2:属性值2:...:} 2.元素(标签)选择器 标签名{属性1:属性值2:属性2:属性 ...

  7. 快速排序&&归并排序

    快速排序 快速排序采用的是分治的策略,算法的具体实现过程是 1.确定一个数X(一般是选中间值X=q[l+r>>1]) 2.利用指针i,j,将数组中比X小的数放在一边,比X大的数放在另一边 ...

  8. centos7 编译安装 redis-6.0.5

    安装redis sudo yum install redis centos自带的redis才3.2 太旧了所以使用源码编译 需要先安装gcc新版才能编译 centos7 默认的 gcc 版本为:4.8 ...

  9. 基于Java的二叉树的三种遍历方式的递归与非递归实现

    二叉树的遍历方式包括前序遍历.中序遍历和后序遍历,其实现方式包括递归实现和非递归实现. 前序遍历:根节点 | 左子树 | 右子树 中序遍历:左子树 | 根节点 | 右子树 后序遍历:左子树 | 右子树 ...

  10. JavaScript学习系列博客_38_JavaScript 事件

    事件(Event) - 事件指的是用户和浏览器之间的交互行为.比如:点击按钮.关闭窗口.鼠标移动.... - 我们可以为事件来绑定回调函数来响应事件. - 绑定事件的方式: 1.可以在标签的事件属性中 ...