1. 程式人生 > 其它 >BFS-八數碼

BFS-八數碼

Acwing845. 八數碼

一道比較難的BFS題目涉及三個過程

  1. 講數串變成3*3的模式
  2. 進行移動(即BFS過程)
  3. 再把它還原成串
#include <iostream>
#include <cstring>
#include <unordered_map>
#include <queue>

using namespace std;

int bfs(string start)
{
    queue<string> q; // BFS需要維護一個佇列來儲存每一步的狀態
    unordered_map<string, int> d; // 建立一個string到int的對映用來計算步數
    
    q.push(start); // 出狀態入隊
    d[start] = 0; // 初始狀態步數記錄為0
    
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
    
    string end = "12345678x"; // 記錄最終狀態
    // BFS
    while(q.size())
    {
        string t = q.front();
        q.pop(); // 取最近狀態
        
        if (t == end) return d[t]; // 返回答案
        
        int distance = d[t]; // 記錄當前距離
        int k = t.find('x'); // find()用於尋找x在字串中的位置,比如123x返回3
        // 對於n行m列且座標從0開始一維轉換二維座標,k為一維座標位置
        // 橫座標x為 x = k / n, 縱座標y為 y = k % n; 
        int x = k / 3, y = k % 3; 
        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)
            {
                // 在範圍內則交換
                swap(t[a * 3 + b], t[k]);
                // 該狀態沒有被找到過則記錄到達該狀態的距離,並講該狀態入隊
                if(!d.count(t))
                {
                    d[t] = distance + 1;
                    q.push(t);
                }
                // 還原,進行下一個方向的操作
                swap(t[a * 3 + b], t[k]);
            }
        }
    }
    return -1;
}
int main()
{
    char c;
    string start;
    for(int i = 0; i < 9; i ++)
    {
        cin >> c;
        start += c;
    }
    
    cout << bfs(start) << endl;
    
    return 0;
}