◇例题·V◇ Gap

搜索训练开始了……POJ的数据比ZOJ强多了!!看来不得不写正解了

+传送门+


◇ 题目

<简要翻译>

有一个四行九列的矩阵——在第1~4行、2~8列上填上数字 11~17,21~27,31~37,41~47(不一定有序)。例子如下:

现在我们将数字11移动在第一行第一列,21移动在第二行第一列,31移动在第三行第一列,41移动在第四行第一列,上面的例子移动后如下:

若一个数x(不是最右边的一列)的右边位置是空位,设x十位为a,个位为b,若b≠7,我们可以把数(10*a+b+1)放在右边的空格处。

比如上图的35的右边是空格,且个位是5(不是7),我们可以把36移动到右边的空格处:

最后的目标是把矩阵变成下面这样:

最少需要移动多少次(不包含一开始移动11,21,31,41)?

<输入输出>

包含多组数据,第一行是整数T,表示数据组数。

每组数据包含一个4*7的矩阵,表示一开始的矩阵的第1~4行、2~8列。

输出最少需要移动多少次,如果不能达到目标,输出-1。


◇ 解析

A) 准备

为了方便最后判断,先const一个常量矩阵gal,表示目标矩阵。输入过后,按照题目要求先模拟把11,21,31,41移动到第一列。

B) 哈希

算是一个矩阵Hash的模板吧……也不知道原理是什么。大概意思就是把矩阵的元素排成一列(第二行接在第一行后面,其他类似),然后将该序列的每一个元素都拆分成相等的位数。因为这道题的矩阵中的元素最大只有两位,所以只需要把每一个元素都拆分成十位和个位就行了。

然后我们得到了一个长度为cnt的序列A,则 hash=7cnt*A[0]+7cnt-1*A[1]+7cnt-2*A[2]+...+71*A[cnt-1]+70*A[cnt]

最后hash先与上一个0x7fffffff再模上一个 MOD=1000007。

ll Hash(const int A[][8]) {
int cnt=0;
ll ret=0,chc[105]= {};
for(int i=0; i<4; i++)
for(int j=0; j<8; j++)
chc[++cnt]=A[i][j]%10,
chc[++cnt]=A[i][j]/10;
for(int i=1; i<=cnt; i++)
ret=ret*7+chc[i];
return (ret&0x7fffffff)%MOD;
}

所以我们可以把目标状态的hash值储存为ovr,则只需要判断当前状态的hash值是否是ovr就可以了。

C) BFS

普通的DFS,就像八数码一样……实在想加快的话可以用双向搜索,因为我们知道终止状态……QwQ


◇ 源代码

/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; typedef long long ll;
const int gal[4][8]= {
11,12,13,14,15,16,17,0,
21,22,23,24,25,26,27,0,
31,32,33,34,35,36,37,0,
41,42,43,44,45,46,47,0
};
const int MOD=1000007; struct QUEUE {
int A[4][8],pos[4][2];
int stp;
} beg;
bool vis[MOD+5];
int ovr; void Clear() {
memset(&beg,0,sizeof &beg);
memset(vis,false,sizeof vis);
}
ll Hash(const int A[][8]) {
int cnt=0;
ll ret=0,chc[105]= {};
for(int i=0; i<4; i++)
for(int j=0; j<8; j++)
chc[++cnt]=A[i][j]%10,
chc[++cnt]=A[i][j]/10;
for(int i=1; i<=cnt; i++)
ret=ret*7+chc[i];
return (ret&0x7fffffff)%MOD;
}
pair<int,int> Search(int A[][8],int val) {
for(int i=0; i<4; i++)
for(int j=0; j<8; j++)
if(A[i][j]==val)
return make_pair(i,j);
}
int BFS() {
int hash_beg=Hash(beg.A);
if(hash_beg==ovr) return 0;
vis[hash_beg]=true;
queue<QUEUE> que;
que.push(beg);
while(!que.empty()) {
QUEUE pre=que.front();
que.pop();
for(int i=0; i<4; i++)
for(int j=0; j<7; j++)
if(!pre.A[i][j+1]) {
if(pre.A[i][j]%10==7 || !pre.A[i][j]) continue;
QUEUE now=pre;
pair<int,int> res=Search(now.A,pre.A[i][j]+1);
swap(now.A[i][j+1],now.A[res.first][res.second]);
now.stp++;
int HASH=Hash(now.A);
if(HASH==ovr) return now.stp;
if(vis[HASH]) continue;
vis[HASH]=true;
que.push(now);
}
}
return -1;
}
int main() {
int T;
scanf("%d",&T);
ovr=Hash(gal);
while(T--) {
Clear();
for(int i=0,cnt=0; i<4; i++) {
for(int j=1; j<8; j++) {
scanf("%d",&beg.A[i][j]);
if(beg.A[i][j]%10==1) beg.A[i][j]=0;
}
beg.A[i][0]=(i+1)*10+1;
}
printf("%d\n",BFS());
}
return 0;
}

  


The End

Thanks for reading!

- Lucky_Glass

(Tab:如果我有没讲清楚的地方可以直接在邮箱lucky_glass@foxmail.com email我,在周末我会尽量解答并完善博客~

【例题收藏】◇例题·V◇ Gap的更多相关文章

  1. 【例题收藏】◇例题·6◇ 电压机制(voltage)

    ◆例题·6◆ 电压机制 周六日常模拟赛……已经不知道该说什么了(感觉做不出来的都是好题) ▷ 题目 (终于不用自己翻译英文题了╮(╯-╰)╭) [问题描述] 科学家在“无限神机”(Infinity M ...

  2. 【例题收藏】◇例题·III◇ 木と整数 / Integers on a Tree

    ◇例题·III◇ 木と整数 / Integers on a Tree 只需要一个美妙的转换,这道题就会变得无比美妙…… 来源:+AtCoder 2148(ARC-063 E)+ ◆ 题目大意 给定一棵 ...

  3. 【例题收藏】◇例题·II◇ Berland and the Shortest Paths

    ◇例题·II◇ Berland and the Shortest Paths 题目来源:Codeforce 1005F +传送门+ ◆ 简单题意 给定一个n个点.m条边的无向图.保证图是连通的,且m≥ ...

  4. 【例题收藏】◇例题·I◇ Snuke's Subway Trip

    ◇例题·I◇ Snuke's Subway Trip 题目来源:Atcoder Regular 061 E题(beta版) +传送门+ 一.解析 (1)最短路实现 由于在同一家公司的铁路上移动是不花费 ...

  5. 【例题收藏】◇例题·IV◇ Wooden Sticks

    ◇例题·IV◇ Wooden Sticks 借鉴了一下 Candy? 大佬的思路 +传送门+ (=^-ω-^=) 来源:+POJ 1065+ ◆ 题目大意 有n个木棍以及一台处理木棍的机器.第i个木棍 ...

  6. HDU 3879 Base Station(最大权闭合子图)

    经典例题,好像说可以转化成maxflow(n,n+m),暂时只可以勉强理解maxflow(n+m,n+m)的做法. 题意:输入n个点,m条边的无向图.点权为负,边权为正,点权为代价,边权为获益,输出最 ...

  7. 网络流 ISAP算法

    网络流问题: 我自己理解,在流网络中,在不违背容量限制的条件下,解决各种从源点到汇点的问题. ISAP算法概念: 据说不会有卡ISAP时间的题目---时间复杂度O(E^2*V) 首先原理都是基于不断寻 ...

  8. 【模板】有源汇有上下界最大流(网络流)/ZOJ3229

    先导知识 无源汇有上下界可行流 题目链接 https://vjudge.net/problem/ZOJ-3229 https://www.luogu.com.cn/problem/P5192 (有改动 ...

  9. (整理)ubuntu 的 相关知识(来自 鸟哥的私房菜)

    1. Linux 文件权限概念 $ ls 察看文件的指令 $ ls -al 出所有的文件详细的权限与属性 (包含隐藏档,就是文件名第一个字符为『 . 』的文件) 在你第一次以root身份登入Linux ...

随机推荐

  1. wampserver启动时图标不变绿的解决方法

    有2种可能: 1.你安装wamp的时候安装路径中有中文,把路径全部改为英文. 2.其他软件占用了80端口号,解决方法是在服务中找微软的sql server或者其他服务,关掉服务后重启就行了.

  2. HDU 4512——吉哥系列故事——完美队形I——————【LCIS应用】

    吉哥系列故事——完美队形I Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  3. 基于JQUERY 的图片查看插件

    viewer是一款功能强大的图片查看器.它可以实现ACDsee等看图软件的部分功能.它可以对图片进行移动,缩放,旋转,翻转,可以前后浏览一组图片.该图片查看器还支持移动设备,支持键盘控制,功能十分强大 ...

  4. Debug Diagnostics Tool创建.Net异常转储并用Windbg分析异常

    当我们要在IIS PRD环境下分析异常,并且对问题毫无头绪,又没有权限直接上打Log的代码.这个时候就是Debug Diagnostics Tool & Windbg大显神威的时候了. Deb ...

  5. Java基础入门 - 三种注释及文档注释详解

    类似C/C++,Java也支持单行和多行注释 注释中的字符在编译时会被忽略 注释通常为类.变量和方法的主要描述 单行注释 // 注释内容 多行注释 /* 注释内容 */ /* * 注释内容 */ 文档 ...

  6. yield关键字的使用

    yield的中文是什么意思呢? 在金山词霸上面的翻译是: vt.屈服,投降: 生产: 获利: 不再反对 vi.放弃,屈服: 生利: 退让,退位 n.产量,产额: 投资的收益: 屈服,击穿: 产品 个人 ...

  7. springmvc+spring+mybatis+sqlserver----插入一条新数据

    <insert id="addOneMsg" parameterType="java.util.Map"> INSERT INTO PDA_JWL_ ...

  8. Python介绍以及Python环境搭建

    Python介绍以及Python环境搭建 1.Python 发展历史 Python是由Guido van Rossum在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的,据说是在圣诞 ...

  9. eclipse 构建从 SVN 上下载的可识别的 maven 项目

    从 SVN 上下载的 maven 项目中含有父项目,属于 maven 的嵌套,每个子项目和父项目虽有 pom.xml 文件,在结构上也是 maven 然而并不是 eclipse 识别的 maven 项 ...

  10. Struts2_模块包含

    <include file="login.xml"/> 包含其他的模块. 项目开发中,分模块协调开发有用. 链接: http://pan.baidu.com/s/1bo ...