[AcWing 179] 八数码


image
image

A* 算法


点击查看代码
#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int,string> PIS;

const int N = 1e6 + 10;

string start;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
char op[] = {'u', 'r', 'd', 'l'};

int f(string s)
{
    int res = 0;
    for (int i = 0; i < s.size(); i ++)
        if (s[i] != 'x') {
            int t = s[i] - '1';
            res += abs(i / 3 - t / 3) + abs(i % 3 - t % 3);
        }
    return res;
}

string bfs()
{
    string end = "12345678x";
    unordered_map<string, int> d;
    unordered_map<string, pair<string,char>> pre;
    priority_queue<PIS, vector<PIS>, greater<PIS>> heap;
    
    heap.push({f(start), start});
    d[start] = 0;

    while (heap.size()) {
        auto t = heap.top();
        heap.pop();
        string s = t.second;
        if (s == end)
            break;
        int step = d[s];
        int p = s.find('x');
        int x = p / 3, y = p % 3;
        string pre_s = s;
        for (int i = 0; i < 4; i ++) {
            int a = x + dx[i], b = y + dy[i];
            if (a < 0 || a >= 3 || b < 0 || b >= 3)
                continue;
            swap(s[x * 3 + y], s[a * 3 + b]);
            if (!d.count(s) || d[s] > step + 1) {
                d[s] = step + 1;
                pre[s] = {pre_s, op[i]};
                heap.push({d[s] + f(s), s});
            }
            swap(s[x * 3 + y], s[a * 3 + b]);
        }
    }
    string res;
    while (end != start) {
        res += pre[end].second;
        end = pre[end].first;
    }
    reverse(res.begin(), res.end());
    return res;
}

void solve()
{
    char c;
    while (cin >> c) {
        start += c;
    }
    int t = 0;
    for (int i = 0; i < start.size(); i ++)
        for (int j = i + 1; j < start.size(); j ++) {
            int s1 = start[i], s2 = start[j];
            if (s1 == 'x' || s2 == 'x')
                continue;
            if (s1 > s2)
                t ++;
        }
    if (t % 2)
        cout << "unsolvable" << endl;
    else
        cout << bfs() << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    solve();

    return 0;
}

  1. 八数码问题
    设 /(s/) 为输入字符串去掉 /(x/) 后的字符串
    ① 当 /(s/) 的逆序对个数为奇数时,无解
    ② 当 /(s/) 的逆序对个数为偶数时,有解
  2. 估价函数
    /(1/) ~ /(8/) 每个数和最终位置的曼哈顿距离之和,这个距离之和小于真实的移动次数,满足 /(A^{*}/) 算法估价值小于真实值的条件
  3. 在原来八数码问题的基础上,用 /(A^{*}/) 算法缩小搜索范围,并且记录方案

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/279369.html

(0)
上一篇 2022年8月7日
下一篇 2022年8月7日

相关推荐

发表回复

登录后才能评论