洛谷P1379 八数码难题 题解 A*搜索

题目链接:https://www.luogu.com.cn/problem/P1379

一般搜索:

#include <bits/stdc++.h>
using namespace std;
int tmp[3][3], dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };
int parse(int s, int d) {
    for (int i = 0; i < 3; i ++) {
        for (int j = 0; j < 3; j ++) {
            tmp[i][j] = s % 10;
            s /= 10;
        }
    }
    int x, y;
    for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) if (!tmp[i][j]) x = i, y = j;
    int xx = x + dir[d][0], yy = y + dir[d][1];
    if (xx >= 0 && xx < 3 && yy >= 0 && yy < 3) {
        swap(tmp[x][y], tmp[xx][yy]);
        int res = 0, t = 1;
        for (int i = 0; i < 3; i ++) {
            for (int j = 0; j < 3; j ++) {
                res += tmp[i][j] * t;
                t *= 10;
            }
        }
        return res;
    }
    else return -1;
}
map<int, int> mp;
int a;
queue<int> que;
int main() {
    cin >> a;
    if (a == 123804765) {
        puts("0");
        return 0;
    }
    mp[a] = 0;
    que.push(a);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        int dis = mp[u];
        for (int i = 0; i < 4; i ++) {
            int v = parse(u, i);
            if (v == -1 || mp.find(v) != mp.end()) continue;
            mp[v] = dis + 1;
            if (v == 123804765) {
                cout << dis + 1 << endl;
                return 0;
            }
            que.push(v);
        }
    }
    return 0;
}

A星搜索:

#include <bits/stdc++.h>
using namespace std;

const int target[3][3] = { 1, 2, 3, 8, 0, 4, 7, 6, 5 };
struct Matrix {
    int a[3][3];
    int to_int() {
        int res = 0;
        for (int i = 0; i < 3; i ++)
            for (int j = 0; j < 3; j ++)
                res = res * 10 + a[i][j];
        return res;
    }
};
int h(Matrix a) {   // 返回有多少个位置和终点不一样
    int cnt = 0;
    for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++)
        if (a.a[i][j] != target[i][j]) cnt ++;
    return cnt;
}
struct Node {
    Matrix a;   // 当前格子的状态
    int step;   // 一共走了多少步
    bool operator < (Node b) const {
        return step + h(a) > b.step + h(b.a);
    }
};
bool check(Node u) {
    for (int i = 0; i < 3; i ++)
        for (int j = 0; j < 3; j ++)
            if (u.a.a[i][j] != target[i][j])
                return false;
    return true;
}
priority_queue<Node> que;
char s[11];
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };
set<int> st;
int main() {
    scanf("%s", s);
    Node u;
    for (int i = 0; i < 3; i ++)
        for (int j = 0; j < 3; j ++)
            u.a.a[i][j] = s[i*3+j] - '0';
    u.step = 0;
    que.push(u);
    while (!que.empty()) {
        Node u = que.top();
        que.pop();
        if (check(u)) {
            printf("%d
", u.step);
            return 0;
        }
        int x, y;
        for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++)
            if (u.a.a[i][j] == 0) x = i, y = j;
        for (int i = 0; i < 4; i ++) {
            Node v = { u.a, u.step+1 };
            int xx = x + dir[i][0], yy = y + dir[i][1];
            if (xx >= 0 && xx < 3 && yy >= 0 && yy < 3) {
                swap(v.a.a[x][y], v.a.a[xx][yy]);
                int val = v.a.to_int();
                if (st.count(val)) continue;
                st.insert(val);
                que.push(v);
            }
        }
    }
    puts("-1"); // 按照题目保证不会出现这种情况
    return 0;
}
原文地址:https://www.cnblogs.com/quanjun/p/13687865.html