【算法】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需要从最后的状 ...
随机推荐
- 2019-3-10——生成对抗网络GAN---生成mnist手写数字图像
""" 生成对抗网络(GAN,Generative Adversarial Networks)的基本原理很简单: 假设有两个网络,生成网络G和判别网络D.生成网络G接受一 ...
- 二维背包 hdu2159
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 题目里面有两个限制条件,忍耐度和杀怪数量,所以可以用一个二维数组dp[i][j]来表示在消耗忍耐 ...
- 51nod 1163 最高的奖励
链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1163 1163 最高的奖励 基准时间限制:1 秒 空间限制:13 ...
- 江西财经大学第一届程序设计竞赛 H题 求大数的阶乘
链接:https://www.nowcoder.com/acm/contest/115/H 来源:牛客网 晚上,小P喜欢在寝室里一个个静静的学习或者思考,享受自由自在的单身生活. 他总是能从所学的知识 ...
- iOS版本设置
Base SDK指的是当前编译所用的SDK 版本: iOS Deployment Target指的是,编译后的 app 可在 终端的哪个 版本上运行. 设置方法: 点击xcode工程左侧项目名称-&g ...
- AVAudioSession应用指南
转coco-LG audiosession负责调节你的app和ios系统里的音频行为.一旦加载了audiosession你可以获得一个audiosession的单例.你可以配置这个audiosessi ...
- httpclient的简单使用
1.通过get请求后台,注意tomcat的编码设置成utf-8; <Connector connectionTimeout="20000" port="808 ...
- MyBatis入门程序(1)
一.入门程序: 1.mybatis的配置文件SqlMapConfig.xml 配置mybatis的运行环境,数据源.事务等. <?xml version="1.0" enco ...
- mysql乐观锁总结和实践(二)
一篇文章<MySQL悲观锁总结和实践>谈到了MySQL悲观锁,但是悲观锁并不是适用于任何场景,它也有它存在的一些不足,因为悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占 ...
- webpack.base.conf.js
var path = require('path')var utils = require('./utils')var config = require('../config')var vueLoad ...