日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AcWing 845. 八数码(3阶数字华容道):bfs求最短路,状态表示困难

發布時間:2025/4/5 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AcWing 845. 八数码(3阶数字华容道):bfs求最短路,状态表示困难 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 題目
      • 題目分析

題目

題目鏈接:AcWing 845. 八數碼(數字華容道)

在一個3×3的網格中,1~8這8個數字和一個“x”恰好不重不漏地分布在這3×3的網格中。

例如:

1 2 3
x 4 6
7 5 8

在游戲過程中,可以把“x”與其上、下、左、右四個方向之一的數字交換(如果存在)。

我們的目的是通過交換,使得網格變為如下排列(稱為正確排列):

1 2 3
4 5 6
7 8 x

例如,示例中圖形就可以通過讓“x”先后與右、下、右三個方向的數字交換成功得到正確排列。

交換過程如下:

1 2 3 \ 1 2 3 \ 1 2 3\ 1 2 3
x 4 6 \ 4 x 6 \4 5 6 \4 5 6
7 5 8 \ 7 5 8 \7 x 8 \7 8 x
現在,給你一個初始網格,請你求出得到正確排列至少需要進行多少次交換。

輸入格式
輸入占一行,將3×3的初始網格描繪出來。

例如,如果初始網格如下所示:

1 2 3
x 4 6
7 5 8

則輸入為:1 2 3 x 4 6 7 5 8

輸出格式
輸出占一行,包含一個整數,表示最少交換次數。

如果不存在解決方案,則輸出”-1”。

輸入樣例:
2 3 4 1 5 x 7 6 8
輸出樣例
19

題目分析

任意的初始狀態start,比如是start=“23415x769”,最終狀態是end=“12345678x” 求初始狀態變成 最終狀態end的最少步數。

這里需要抽象一下,將一個狀態(一個字符串) 抽象成圖中的一個結點a,如果一個狀態可以變成另一個狀態b,就在圖中兩個結點a和b之間建立一條有向邊a→ba\rightarrow bab,邊的權值是1.

那么該問題就變成:給定一個起點 和一個終點,從起點到終點最少走多少步。 可以使用BFS()來求最短路。

BFS()需要兩個數據結構:1個隊列queue,一個距離數組dist[ ]

難點如下:

  • 狀態表示復雜:這里每個狀態是一個3 ×3的小矩陣
  • 如何記錄每個狀態到初始狀態的距離
  • 解決方法:

  • 用一個字符串表示一個3 ×3的小矩陣,比如是start=“23415x769”,最終狀態是end=“12345678x” ,那么隊列就可以是queue<string>
  • 距離用哈希表來存,unordered_map<string ,int>
  • 想明白這些表示的問題,真正的難點在于如何實現狀態轉移

    start="23415x769"這個狀態可以狀態成幾種狀態?
    1) 需要把這個一維字符串轉換成二維的小矩陣
    映射方法(假設矩陣每行m個數) 則 一維下標t轉換為二維下標(x,y) 有如下公式:

    x= t /m; //m是矩陣每行元素個數,本例中 m = 3 y=t% m;

    2)狀態轉移:二維矩陣中的點(x,y)可以轉移到它的上下左右四個方向。

    3)最后再將二維矩陣坐標映射成1維字符串中的下標。
    二維小矩陣中坐標恢復到一維坐標:

    t= x * m+ y; //m是矩陣每行元素個數,本例中 m = 3

    然后就是標準的bfs模板。
    請看代碼:

    ac代碼

    #include<iostream> #include<algorithm> #include<unordered_map> #include<queue>#include<string> using namespace std;int bfs(string start){string end="12345678x";//終點queue<string> q; unordered_map<string,int> d;//距離數組q.push(start);d[start]=0;int dx[4]={0,0,-1,1}, dy[4]={1,-1,0,0};while(q.size()){auto t=q.front();//t為字符串q.pop();int dist=d[t];if(t==end) return dist; //到了終點 返回 dist//狀態轉移int k=t.find('x'); //找到x的位置//一維數組下標轉化為二維數組下標(x,y)int x= k/3,y=k %3; //(x,y)為空格x的位置for(int i=0;i<4;i++){int a= x + dx[i] , b =y +dy[i]; //(a,b)為空格上下左右的某一個值if(a>= 0 && a<3 && b>=0 && b<3 ){swap(t[k],t[a*3+b]); //二維下標對應到一維下標 ,狀態更新if(!d.count(t)){ //之前沒搜到d[t]=dist+1;q.push(t);}swap(t[k],t[a*3+b]); //狀態恢復}}}return -1; //到不了終點 返回-1 }int main(){string start;for(int i=0;i<9;i++){char c;cin>>c;start+= c;}cout<<bfs(start) <<endl;return 0;}

    總結

    以上是生活随笔為你收集整理的AcWing 845. 八数码(3阶数字华容道):bfs求最短路,状态表示困难的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。