首页 > 代码库 > graph-bfs-八数码问题

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;
    }

  

 

graph-bfs-八数码问题