这个看起来是童年回忆:)

大体思路是,将每个排列状态看成图中的一个点,状态之间转换说明有边。然后用bfs,如果遍历完之后还是没有找到目标状态,

则说明是无解的,否则输出步数。具体想法写在代码里吧,多多理解。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <cmath>
#include <vector>
#include <algorithm> using namespace std;
const int N = 1000000, HN = 1000003;
// linked list for hash table.
int head[HN], next[N];
int state[N][9], goal[9];
// # steps
int dist[N];
const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1}; // map into a number of 9 digits
int hash(int *arr) {
int v = 0;
for (int i = 0; i < 9; i++) {
v = v * 10 + arr[i];
}
// make sure not overflow
return v % HN;
}
// insert a state
bool tryInsert(int rear) {
int h = hash(state[rear]);
int u = head[h];
while (u) {
// if repeated
if (!memcmp(state[u], state[rear], sizeof(state[0])))
return false;
u = next[u];
}
// insert rear to the front
next[rear] = head[h];
head[h] = rear;
return true;
}
int bfs() {
// initiate head
memset(head, 0, sizeof(head));
//memset(dist, 0, sizeof(dist));
int front = 1;
int rear = 2;
while (front < rear) {
// same, memcmp return 0
// means find goal
if (!memcmp(goal, state[front], sizeof(state[0])))
return front;
int z;
// find 0
for (z = 0 ; z < 9; z++)
if (!state[front][z])
break;
int x = z / 3;
int y = z % 3;
for (int d = 0; d < 4; d++) {
int nx = x + dx[d];
int ny = y + dy[d];
int nz = 3 * nx + ny;
// judge if still in
if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3) {
memcpy(&state[rear], &state[front], sizeof(state[0]));
// move
state[rear][nz] = state[front][z];
state[rear][z] = state[front][nz];
dist[rear] = dist[front] + 1;
if (tryInsert(rear))
rear ++;
}
}
// front pop
front ++;
}
return 0;
}
int main() {
//freopen("hhInput.in", "r", stdin);
for (int i = 0; i < 9; i++)
// 1 3 0 8 2 4 7 6 5
cin >> state[1][i];
for (int i = 0; i < 9; i++)
// 1 2 3 8 0 4 7 6 5
cin >> goal[i];
int ans = bfs();
if (ans > 0)
cout << dist[ans] << endl;
else
cout << "-1" << endl;
return 0;
}

  

graph-bfs-八数码问题的更多相关文章

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

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

  2. UVALive 6665 Dragon’s Cruller --BFS,类八数码问题

    题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <i ...

  3. [cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)

    快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚 ...

  4. 八数码问题+路径寻找问题+bfs(隐式图的判重操作)

    Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 p ...

  5. HDU 1043 Eight (BFS&#183;八数码&#183;康托展开)

    题意  输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数  即这个排列在全部排列中的字典序  然后就是基础的BFS了 #include <bits/stdc++.h ...

  6. 【算法】BFS+哈希解决八数码问题

    15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...

  7. hdu-1043(八数码+bfs打表+康托展开)

    参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html 康托展开:https://blog.csdn.net/wbin233/article/deta ...

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

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

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

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

  10. 习题:八数码难题(双向BFS)

    八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...

随机推荐

  1. 【aspnetcore】抓取远程图片

    找到要抓取的图片地址:http://i.imgur.com/8S7OaEB.jpg 抓取的步骤: 请求图片路径 获取返回的数据 将数据转换为stream 将stream转换为Image 保存Image ...

  2. 安卓第四次作业——简单校园二手交易APP

    一.项目团队 团队成员 姓名:汤文涛 学号:1600802129 班级:计算机164班 博客地址:https://www.cnblogs.com/taotao01/ 姓名:杨圣豪 学号:1600802 ...

  3. vs2012 support BI

    Microsoft SQL Server Data Tools - Business Intelligence for Visual Studio 2012 http://www.microsoft. ...

  4. 六,IO系统

    六,IO系统 一,数据源 1,数据源--管道确认使用那根管道--节点流 2,先确定管道在tey中new出管道,new出后就写关闭代码,写完关闭代码在写中间代码 3,取数据和放数据结束语句必须有两个,不 ...

  5. Java输入输出流简单案例

    package com.jckb; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io. ...

  6. AJPFX辨析Java中堆内存和栈内存的区别

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  7. 密码强度的正则表达式(JavaScript)总结

    简言 本文给出了两个密码强度的正则表达式方案,一个简单,一个更复杂和安全.并分别给出了两个方案的解析和测试程序.一般大家可以根据自己的项目的实际需要,自行定义自己的密码正则约定. 前言 用户注册时,都 ...

  8. 字典(dict),增删改查,嵌套

    一丶字典 dict 用{}来表示  键值对数据  {key:value}  唯一性 键 都必须是可哈希的 不可变的数据类型就可以当做字典中的键 值 没有任何限制 二丶字典的增删改查 1.增 dic[k ...

  9. C# List的使用

    1.所需引入的命名空间: using System.Collections.Generic; 2.初始化 [1]空: List<int> list = new List<int> ...

  10. WEB网页如何让背景图片跟随可视窗口自适应大小

    HTML代码 <body id="body"> <div class="info-wrapper"> <div class=&qu ...