力扣--- 滑动谜题
生活随笔
收集整理的這篇文章主要介紹了
力扣--- 滑动谜题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
力扣— 滑動謎題
文章目錄
- 力扣--- 滑動謎題
- 一、題目描述
- 二、問題分析
- 三、代碼
一、題目描述
二、問題分析
對于這種計算 最小步數的問題,我們就要敏感地想到 BFS 算法。
這個題目轉化成 BFS 問題是有一些技巧的,我們面臨如下問題:
- 1、一般的 BFS算法,是從一個起點start開始,向終點target進行尋路,但是拼圖問題不是在尋路,而是在不斷交換數字,這應該怎么轉化成 BFS算法問題呢?
- 2、即便這個問題能夠轉化成 BFS 問題,如何處理起點start和終點target?它們都是數組哎,把數組放進隊列,套 BFS框架,想想就比較麻煩且低效。
- 首先回答第一個問題,BFS 算法并不只是一個尋路算法,而是一種暴力搜索算法,只要涉及暴力窮舉的問題,BFS就可以用,而且可以最快地找到答案。
- 你想想計算機怎么解決問題的?哪有那么多奇技淫巧,本質上就是把所有可行解暴力窮舉出來,然后從中找到一個最優解罷了。
- 明白了這個道理,我們的問題就轉化成了:如何窮舉出board當前局面下可能衍生出的所有局面?這就簡單了,看數字 0 的位置唄,和上下左右的數字進行交換就行了:
- 這樣其實就是一個 BFS 問題,每次先找到數字 0,然后和周圍的數字進行交換,形成新的局面加入隊列……當第一次到達target時,就得到了贏得游戲的最少步數。
- 對于第二個問題,我們這里的board僅僅是 2x3 的二維數組,所以可以壓縮成一個一維字符串。其中比較有技巧性的點在于,二維數組有「上下左右」的概念,壓縮成一維后,如何得到某一個索引上下左右的索引?
很簡單,我們只要手動寫出來這個映射就行了:
vector<vector<int>> neighbor = {{ 1, 3 },{ 0, 4, 2 },{ 1, 5 },{ 0, 4 },{ 3, 1, 5 },{ 4, 2 } };這個含義就是,在一維字符串中,索引i在二維數組中的的相鄰索引為neighbor[i]
三、代碼
至此,我們就把這個問題完全轉化成標準的 BFS 問題了,借助之前 BFS 算法框架套路詳解 的代碼框架(算法模塊的博客),直接就可以套出解法代碼了:
int slidingPuzzle(vector<vector<int>>& board) {int m = 2, n = 3;string start = "";string target = "123450";// 將 2x3 的數組轉化成字符串for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {start.push_back(board[i][j] + '0');}}// 記錄一維字符串的相鄰索引vector<vector<int>> neighbor = {{ 1, 3 },{ 0, 4, 2 },{ 1, 5 },{ 0, 4 },{ 3, 1, 5 },{ 4, 2 }};/******* BFS 算法框架開始 *******/queue<string> q;unordered_set<string> visited;q.push(start);visited.insert(start);int step = 0;while (!q.empty()) {int sz = q.size();for (int i = 0; i < sz; i++) {string cur = q.front(); q.pop();// 判斷是否達到目標局面if (target == cur) {return step;}// 找到數字 0 的索引int idx = 0;for (; cur[idx] != '0'; idx++);// 將數字 0 和相鄰的數字交換位置for (int adj : neighbor[idx]) {string new_board = cur;swap(new_board[adj], new_board[idx]);// 防止走回頭路if (!visited.count(new_board)) {q.push(new_board);visited.insert(new_board);}}}step++;}return -1;/******* BFS 算法框架結束 *******/ }至此,這道題目就解決了,其實框架完全沒有變,套路都是一樣的,我們只是花了比較多的時間將滑動拼圖游戲轉化成 BFS 算法。
總結
以上是生活随笔為你收集整理的力扣--- 滑动谜题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态规划套路:最大子数组和
- 下一篇: DjangoORM框架