https://www.luogu.org/problem/show?pid=T2485

题目背景

汉诺塔升级了

题目描述

现在我们有N个圆盘和N个柱子,每个圆盘大小都不一样,大的圆盘不能放在小的圆盘上面,N个柱子从左向右排成一排。每次你可以将一个柱子的最上面的圆盘移动到右边或者左边的柱子上(如果移动是合法的话)。现在告诉你初始时的状态,你希望用最少的步数将第i大的盘子移动到第i根柱子上,问最小步数。

输入输出格式

输入格式:

第一行一个整数T,代表询问的组数。

接下来T组数据,每组数据第一行一个整数N。

接下来一行N个正整数,代表每个柱子上圆盘的大小。

输出格式:

输出共T行,代表每次的答案。如果方案不存在,输出-1;

输入输出样例

输入样例#1:

4
3
2 1 3
2
7 8
2
10000 1000
3
97 96 95
输出样例#1:

4
0
-1
20

说明

对于70%的数据,N的值都是相等的。

对于100%的数据,1≤T≤6 x 10^3 ; 1≤N≤7。

其实这个题其实是打表啊…..用BFS打表,然后对应询问直接输出,时空复杂度大丈夫。

对于读入进来的数据,离散化一下,用z数组记录这个盘子是第几大。

用bit数组记录位,这个是当你移动盘子的时候有用的….(具体我也说不太清楚,看代码理解理解吧。) 
我们开一个top和place数组,分别记录第i个柱子的最上面的盘子,和当前盘子在哪根柱子上, 
预处da理biao的时候,首先从初始状态开始搜(1,12,123,1234……1234567) 
每搜到一个新的可能状态,就把这个状态记录下来。(试想一下,从某个给定状态到初始状态的步数==从初始状态的步数到给定状态的步数) 
细节处理的话,直接看代码吧。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int n,top[],place[],bit[];//最上面|每个盘子位置 |进制保存
int res[maxn];//答案
int q[maxn];//队列 int front,tail;//队列头尾指针
int w[],z[];//z为离散化后的大小
bool use[maxn];
bool cmp(int a,int b)
{
return w[a]<w[b];
}//按大小排序
void analyze(int s)
{
int x=;
int ss=s;
for (int a=;a<=;a++)
top[a]=;//最上面的
while (ss)
{
x++;
place[x]=ss%;//初始盘子位置(处理是反着的)
ss/=;
}
reverse(place+,place+x+);//逆转 (一个奇怪的函数) for (int a=x;a>=;a--)
top[place[a]]=a;
//初始最上面位置 即1 2 3 4 5 6 7 for (int a=;a<=x;a++)
{
if (a==top[place[a]])//a在某个柱子的最上面//移动的时候,是直接往左移动一个柱子或直接往右移一个柱子
{
int p=place[a];//那个柱
if (p!= && (a<top[p-] || !top[p-]))//小或者空
{
int news=s-bit[x-a];//新状态
if (!use[news])
{
q[++tail]=news;
use[news]=true;
res[news]=res[s]+;//因为是宽搜,第一次搜到的就是最小的。
}
}//左移
if (p!=x && (a<top[p+] || !top[p+]))
{
int news=s+bit[x-a];
if (!use[news])
{
q[++tail]=news;//orz 钟小鸟
use[news]=true;
res[news]=res[s]+;
}
}//右移
}
} } int main()
{
// freopen("huakai.in","r",stdin);
// freopen("huakai.out","w",stdout);
front=,tail=;
int status=;
bit[]=;
for(int a=;a<=;a++)
{
bit[a]=bit[a-]*;
status=status*+a;//1 12 123 1234
q[++tail]=status;//1 12 134 1234
use[status]=true;//1 12 123 1234
}//bit 10 100 1000 10000...
for(;front<=tail;)
{
int s=q[front++];//
analyze(s);//
}
printf("%d",tail);
int t;
scanf("%d",&t);
for(;t--;)
{
scanf("%d",&n); for (int a=;a<=n;a++)
scanf("%d",&w[a]),z[a]=a;//按编号sort
sort(z+,z+n+,cmp); int s=;
for (int a=;a<=n;a++)
s=s*+z[a];//盘子大小序列 if (!use[s]) printf("-1\n");//移动不到
else printf("%d\n",res[s]);
}
return ;
}

T2485 汉诺塔升级版(普及)(递归)的更多相关文章

  1. 汉诺塔算法的递归与非递归的C以及C++源代码

    汉诺塔(又称河内塔)问题其实是印度的一个古老的传说. 开天辟地的神勃拉玛(和中国的盘古差不多的神吧)在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一 个小, ...

  2. python汉诺塔问题的递归理解

    一.问题背景 汉诺塔问题是源于印度一个古老传说. 源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下 ...

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

    百度测试部2015年10月份的面试题之——汉诺塔. 汉诺塔就是将一摞盘子从一个塔转移到另一个塔的游戏,中间有一个用来过度盘子的辅助塔. 百度百科在此. 游戏试玩在此. 用递归的思想解决汉诺塔问题就是分 ...

  4. [Python3 练习] 006 汉诺塔2 非递归解法

    题目:汉诺塔 II 接上一篇 [Python3 练习] 005 汉诺塔1 递归解法 这次不使用递归 不限定层数 (1) 解决方式 利用"二进制" (2) 具体说明 统一起见 我把左 ...

  5. PTA 汉诺塔的非递归实现(C 语言)

    借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b, c), 即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”), 并保证每个移动符合汉诺塔问题的要求 ...

  6. 汉诺塔算法c++源代码(递归与非递归)[转]

     算法介绍: 其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n - 1(有兴趣的可以自己证明试试看).后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了.首先把三根柱 ...

  7. python数据结构_递归_汉诺塔问题

    已经不是第一次写这个汉诺塔问题, 其实递归还真是不太好理解, 因为递归这种是想其实有点反人类, 为什么? 因为不太清楚, 写个循环一目了然, 用递归其实要把核心逻辑理清楚, 要不根本没法进行下去 所有 ...

  8. [Python3 练习] 005 汉诺塔1 递归解法

    题目:汉诺塔 I (1) 描述 传说,在世界中心贝拿勒斯(在印度北部)的圣庙外有左中右三根足够长的柱子(塔) 左边柱子上套着 64 片金片,金片按"上小下大"排,其余两根是空柱子 ...

  9. 汉诺塔问题C++实现

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang 以下进行汉诺塔问题的递归实现 #include <iostream.h> int gb ...

随机推荐

  1. neo4j算法(1)-介绍

    neo4j为图数据库,其中涉及的也就为图算法,图算法被用来度量图形,节点及关系. 在neo4j中,通过call algo.list() 可查看neo4j中的算法列表. 在neo4j官方文档中,主要记录 ...

  2. Bootstrap——可拖动模态框(Model)

    还是上一个小项目,o(╥﹏╥)o,要实现点击一个div或者button或者一个东西然后可以弹出一个浮在最上面的弹框.网上找了找,发现Bootstrap的Model弹出框可以实现该功能,因此学习了一下, ...

  3. 窥探C语言程序的编译、链接与.h文件

    概述 C语言程序从源文件经过编译.链接生成可执行文件.那么编译与链接分别做了什么? 开发中为什么使用.h编写函数的声明?接下来使用案例说清楚为什么这样编写代码. C语言程序的编译和链接 C语言程序从源 ...

  4. arp协议简单介绍

    1. 什么是ARP? ARP (Address Resolution Protocol) 是个地址解析协议.最直白的说法是:在IP以太网中,当一个上层协议要发包时,有了该节点的IP地址,ARP就能提供 ...

  5. Python全栈开发:进程代码实例

    进程与线程的关系 #!/usr/bin/env python # -*- coding;utf-8 -*- """ 多进程(主进程,子进程): 优点:能同时利用多个CPU ...

  6. 企业网盘居然支持高速局域网文件传输工具(速度可达20M)

    高速局域网文件传输工具Mobox,局域网内文件共享是公司内非常必须的功能,原本文件共享可以通过:1)windows目录共享目录来实现文件交互:2)通过U盘拷贝给对方:3)通过QQ发送给对方:4)通过邮 ...

  7. python所有的标准异常类

    异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基类 ...

  8. 【JZOJ3379】查询

    description 对于一个整数序列,查询区间第k大数可以在O(logN)的时间内轻松完成.现在我们对这个问题进行推广. 考虑带重复数的集合(multiset).定义在该类集合上的并操作" ...

  9. 莫烦pytorch学习笔记(二)——variable

    .简介 torch.autograd.Variable是Autograd的核心类,它封装了Tensor,并整合了反向传播的相关实现 Variable和tensor的区别和联系 Variable是篮子, ...

  10. 转:进程上下文VS中断上下文

    源地址:http://www.cnblogs.com/zzx1045917067/archive/2012/12/19/2824552.html 内核空间和用户空间是现代操作系统的两种工作模式,内核模 ...