【算法】BFS+哈希解决八数码问题
15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了。它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失。让我们把丢失的瓷砖“X”; 拼图的目的是安排瓷砖以便它们排序为:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15×
这里唯一合法经营是交流'X'与它共享一个边缘的瓷砖之一。作为一个例子,举动下列顺序解决了一个稍微加扰难题:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9×10 12 9 10×12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14×15 13 14 15×
R-> D-> R->
上一行中的字母指示哪个的“x”瓦片的邻居交换在每一步的“x”瓦片; 合法的值是'R','L','U'和'D',右,左,上,下,分别。
并非所有的难题都可以解决; 在1870年,一个叫萨姆·劳埃德的人是著名的分配难题的一个无法解决的版本,
折腾了不少人。事实上,所有你必须做的,使一个普通的益智成无法解决的一个是交换两个瓷砖(不包括课程的缺失'X'瓦)。
在这个问题中,你会写三个解决不太知名的8益智,砖组成一个三的程序
安排。
思路分析:
从第一步开始,我们每一步都有不多于四种选择:将白格向上移;向下移;向左移;向右移。这很像是做迷宫。走迷宫的任务是走到某一点就算赢。而八数码,是走到什么局面才算赢。那么队列中存放的就不是点,而是面。换句话说,就是图。现在问题变得很简单,只要你能在一张3×3的图上裸着BFS一遍,搜到目标图就算你赢了。就像迷宫的vis数组一样,我们需要对走过的局面设置标记,不要重复走。
在做这道题中学到的几样小技巧:
1. 数组直接用memcpy, memcmp对整块内存进行复制或者比较, 速度比用for循环快。
2.用typedef来定义一个新名称可以更加方便。
3.哈希表与编码的应用
#include<stdio.h>
#include<string.h>
#define MAXN 500000 char input[];
int state[], goal[] = {,,,,,,,,};
int dir[][] = {{-,},{,},{,-},{,}}; // 上,下,左, 右
char path_dir[] = "udlr";
int st[MAXN][];
int father[MAXN], path[MAXN]; // 保存打印路径 const int MAXHASHSIZE = ;
int head[MAXHASHSIZE], next[MAXN]; void init_lookup_table() { memset(head, , sizeof(head)); } typedef int State[];
int hash(State& s) {
int v = ;
for(int i = ; i < ; i++) v = v * + s[i];
return v % MAXHASHSIZE; } int try_to_insert(int s) {
int h = hash(st[s]);
int u = head[h];
while(u) {
if(memcmp(st[u], st[s], sizeof(st[s])) == ) return ;
u = next[u];
}
next[s] = head[h];
head[h] = s;
return ;
} int bfs(){
init_lookup_table();
father[] = path[] = -;
int front=, rear=;
memcpy(st[], state, sizeof(state)); while(front < rear){
int *s = st[front]; if(memcmp(s, goal, sizeof(goal))==){
return front;
} int j;
for(j=; j<; ++j) if(!s[j])break; // 找出0的位置
int x=j/, y=j%; // 转换成行,列 for(int i=; i<; ++i){ int dx = x+dir[i][]; // 新状态的行,列
int dy = y+dir[i][];
int pos = dx*+dy; // 目标的位置 if(dx>= && dx< && dy>= && dy<){
int *newState = st[rear];
memcpy(newState, s, sizeof(int)*);
newState[j] = s[pos];
newState[pos] = ;
if(try_to_insert(rear)){
father[rear] = front; path[rear] = i;
rear++;
}
}
}
front++;
}
return -;
} void print_path(int cur){
if(cur!=){
print_path(father[cur]);
printf("%c", path_dir[path[cur]]);
}
} int main(){ while(gets(input)){
// 转换成状态数组, 'x'用0代替
for(int pos=, i=; i<strlen(input); ++i){
if(input[i]>='' && input[i]<='')
state[pos++] = input[i]-'';
else if(input[i]=='x')
state[pos++] = ;
}
int ans;
if((ans=bfs())!=-){
print_path(ans);
printf("\n");
}
}
}
【算法】BFS+哈希解决八数码问题的更多相关文章
- A*算法解决八数码问题 Java语言实现
0X00 定义 首先要明确一下什么是A*算法和八数码问题? A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法也是一种启发性的算法,也是解决许多搜索问题的有效算法.算法中的距离估 ...
- Poj 1077 eight(BFS+全序列Hash解八数码问题)
一.题意 经典的八数码问题,有人说不做此题人生不完整,哈哈.给出一个含数字1~8和字母x的3 * 3矩阵,如: 1 2 X 3 4 6 7 5 8 ...
- c++ 启发式搜索解决八数码问题
本文对八数码问题 启发式搜索 (C++)做了一点点修改 //fn=gn+hn #include<iostream> #include<queue> #include<st ...
- 【基础练习】【BFS+A*】codevs1225八数码难题题解
题目描写叙述 Description Yours和zero在研究A*启示式算法.拿到一道经典的A*问题,可是他们不会做,请你帮他们. 问题描写叙述 在3×3的棋盘上,摆有八个棋子,每一个棋子上标有1至 ...
- Java实现 蓝桥杯 算法提高 八数码(BFS)
试题 算法提高 八数码 问题描述 RXY八数码 输入格式 输入两个33表格 第一个为目标表格 第二个为检索表格 输出格式 输出步数 样例输入 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 ...
- HDU1043 八数码(BFS + 打表)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表. 经典八数码问题,传说此题不做人生不完整,关于八数码的八境界 ...
- HDU 1043 Eight 八数码问题 A*算法(经典问题)
HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...
- A*算法 -- 八数码问题和传教士过河问题的代码实现
前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...
随机推荐
- Vue-axios快速上手(转)
引入方式: 1 2 3 4 5 $ npm install axios $ cnpm install axios //taobao源 $ bower install axios 或者使用cdn: &l ...
- RecyclerView的单击和长按事件(转)
转自:http://www.jianshu.com/p/f2e0463e5aef 前言 上一篇文章揭开RecyclerView的神秘面纱(一):RecyclerView的基本使用中,主要讲述了Recy ...
- 启动Tomcat的小细节--MyEclipse
1.先停掉Tomcat 2.然后再Redeploy项目 3.然后再启动Tomcat. 这样的好处是 代码彻底编译
- vue / js使用video获取视频时长
项目中遇到上传视频功能,需要有预览和获取视频时长功能,因之前使用upload(有需要的话可以参考下我之前的文章),这里就不赘述,直接用来上传视频,不过在上传之前和上传成功后的钩子里,获取不到时长: 没 ...
- CentOS systemctl命令
systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起. 任务 旧指令 新指令 使某服务自动启动 chkconfig --level 3 ...
- PL/SQL Dev连接Oracle弹出空白提示框的解决方法分享
第一次安装Oracle,装在虚拟机中,用PL/SQL Dev连接远程数据库的时候老是弹出空白提示框,网上找了很久,解决方法也很多,可是就是没法解决我这种情况的. 出现这种问题,解决方法大概有这几种: ...
- Javascript 强制浏览器渲染Dom文档
在Cordova+Framework7开发Hybrid App时,在iPhone 7上遇到一个诡异的现象(Chrome浏览器.Android都正常):js修改手风琴中的input文本框的值后,但页面仍 ...
- 【git】gitignore
gitignore git专门有个文件用来管理那些不被纳入版本库的文件,这个文件是 [.gitignore],所有不被包含的都能放进去,但这个是有前提的. 前提 前提是文件如果没被git客户端trac ...
- PTA 7-9 旅游规划(SPFA)
有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便 ...
- Hive和并行数据仓库的比较
最近分析和比较了Hive和并行数据仓库的架构,本文记下一些体会. Hive是架构在Hadoop MapReduce Framework之上的开源数据分析系统. Hive具有如下特点: 1. 数据以HD ...