graph-bfs-八数码问题

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

大体思路是,将每个排列状态看成图中的一个点,状态之间转换说明有边。然后用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;
    }

  

时间: 2024-10-30 16:43:22

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

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

题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状态逆向搜索,这样才不会超时.判重康托展开,哈希也可. POJ //#include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<string> #include<stack

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

题意  输出八数码问题从给定状态到12345678x的路径 用康托展开将排列对应为整数  即这个排列在所有排列中的字典序  然后就是基础的BFS了 #include <bits/stdc++.h> using namespace std; const int N = 5e5, M = 9; int x[4] = { -1, 1, 0, 0}; int y[4] = {0, 0, -1, 1}; int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

cdoj 1380 Xiper的奇妙历险(2) [八数码问题 bfs + 预处理]

快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚至还用过A*来优化时间.不过这道题懒得写了,就一个普普通通的bfs,再加上一个stl 的map就水过了. 首先题目要求有多达10000组数据,依次搜索肯定是不行的,我试过用A*来写,第2组数据就会T掉,所以我们考虑用一个预处理.从末尾状态搜索所有可行的状态,并用一个map来存储答案.然后就很好写了.

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

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

【算法】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

UVALive 6665 Dragon&#226;??s Cruller --BFS,类八数码问题

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

poj 1077 八数码(BFS+康托展开)

1 /* 2 题意:八数码问题,给出3*3的矩阵含1~8以及x,给出一个符合的解使得移动后的矩阵的顺序为1~8,最后为x 3 4 题解:BFS 5 需要用到康托展开来表示状态,不然数组无法完全表示所有状态,这样BFS就无法判断找不到解的情况(status 6 的0ms,0KB究竟是怎么做到的,简直不能想象=.=) 7 */ 8 #include <cstdio> 9 #include <cstring> 10 #include <queue> 11 #include &

UVA 10085(bfs+康拓展开)八数码问题

Description Problem A The Most Distant State Input: standard input Output: standard output The 8-puzzle is a square tray in which eight square tiles are placed. The remaining ninth square is uncovered. Each tile has a number on it. A tile that is adj

每天刷个算法题20160526:BFS解决八数码问题(九宫格问题)

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524864 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西