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+哈希解决八数码问题的更多相关文章

  1. A*算法解决八数码问题 Java语言实现

    0X00 定义 首先要明确一下什么是A*算法和八数码问题? A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法也是一种启发性的算法,也是解决许多搜索问题的有效算法.算法中的距离估 ...

  2. Poj 1077 eight(BFS+全序列Hash解八数码问题)

    一.题意 经典的八数码问题,有人说不做此题人生不完整,哈哈.给出一个含数字1~8和字母x的3 * 3矩阵,如: 1  2  X            3 4  6            7  5  8 ...

  3. c++ 启发式搜索解决八数码问题

    本文对八数码问题 启发式搜索 (C++)做了一点点修改 //fn=gn+hn #include<iostream> #include<queue> #include<st ...

  4. 【基础练习】【BFS+A*】codevs1225八数码难题题解

    题目描写叙述 Description Yours和zero在研究A*启示式算法.拿到一道经典的A*问题,可是他们不会做,请你帮他们. 问题描写叙述 在3×3的棋盘上,摆有八个棋子,每一个棋子上标有1至 ...

  5. Java实现 蓝桥杯 算法提高 八数码(BFS)

    试题 算法提高 八数码 问题描述 RXY八数码 输入格式 输入两个33表格 第一个为目标表格 第二个为检索表格 输出格式 输出步数 样例输入 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 ...

  6. HDU1043 八数码(BFS + 打表)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表. 经典八数码问题,传说此题不做人生不完整,关于八数码的八境界 ...

  7. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  8. A*算法 -- 八数码问题和传教士过河问题的代码实现

    前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...

  9. BFS(八数码) POJ 1077 || HDOJ 1043 Eight

    题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...

随机推荐

  1. java使用正则表达式

    package com.regexp; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Tes ...

  2. Python设计模式 - 总览(更新中...)

    最近打算重构部分python项目,有道是"工欲善其事,必先利其器",所以有必要梳理一下相关设计模式.每次回顾基本概念或底层实现时都会有一些新的收获,希望这次也不例外. 本系列打算先 ...

  3. vue项目打包后图片路径问题

    当用vue-cli自动构建项目后,有两种运行方法,分别是: npm run dev : 提供一个开发的环境,自动热更新,资源使用绝对路径,所以可以正常看到背景图片. npm run build : 打 ...

  4. Python之逻辑回归模型来预测

    建立一个逻辑回归模型来预测一个学生是否被录取. import numpy as np import pandas as pd import matplotlib.pyplot as plt impor ...

  5. GIRDVIEW 控件绑定数据后 后台c#控制隐藏某列

    gv_EnterpriseInfo.DataSource = pageResult.Data; gv_EnterpriseInfo.DataBind(); 之后加判断条件: if (true) { g ...

  6. [Unity3D]降低向Shader中传值的开销

    Unity3D中提供了很多API用于向shader传值,这篇文章对比测试了两类不同的使用方法的性能. 正文 Unity3D中,通过C#代码向shader传值有两种方式. 一种是面向具体的materia ...

  7. vcenter或workstation12导入ovf出错:硬件系列vmx 14不受支持

    原因是因为导出ovf的虚拟机版本太高. 两个方法,一个强制,一个推荐. 强制 1. 打开ovf后缀文件,把<vssd:VirtualSystemType>vmx-14</vssd:V ...

  8. 【nginx】配置详解

    nginx作为web server,是最常用的网络服务器.来看下它的配置文件. 实验1:最基础的配置(可访问静态资源) 包括listen,server_name,root,index,access_l ...

  9. Wannafly挑战赛13 C:zzf的好矩阵(思维)

    题目描述 一个8 * 8的棋盘,第一个格子放1个麦穗,第二个格子放2个麦穗,第三个格子放4个麦穗……那么最后,共要放几个麦穗呢? zzf表示这个问题实在太简单,于是重新规定了游戏的规则. 初始的棋盘为 ...

  10. f5 2017.09.03故障

    1.下午14点50左右有同事反应epm等系统登录有问题.自测登录也是有同样的报错. 2.测试发现内部IP直接访问正常,但是访问f5的vip的方式访问不了.此时oa.邮件等系统也开始有同事发现故障. 3 ...