目錄
1 問題描述
問題描述
如下面第一個圖的九宮格中,放着 1~8 的數字卡片,還有一個格子空着。與空格子相鄰的格子中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。

我們把第一個圖的局面記為:12345678.
把第二個圖的局面記為:123.46758
顯然是按從上到下,從左到右的順序記錄數字,空格記為句點。
本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。如果無論多少步都無法到達,則輸出-1。


我們把第一個圖的局面記為:12345678.
把第二個圖的局面記為:123.46758
顯然是按從上到下,從左到右的順序記錄數字,空格記為句點。
本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。如果無論多少步都無法到達,則輸出-1。
輸入格式
輸入第一行包含九宮的初態,第二行包含九宮的終態。
輸出格式
輸出最少的步數,如果不存在方案,則輸出-1。
樣例輸入
12345678.
123.46758
123.46758
樣例輸出
3
樣例輸入
13524678.
46758123.
46758123.
樣例輸出
22
2 解決方案
本題下面代碼參考自文末參考資料,本題的核心使用BFS求解,其中要求最小移動次數,在BFS遍歷中,第一次達到匹配時就是最小移動次數,這個不好證明,不過可以自己細細想想,應該是這樣。
該版本的C++版是100分,Java版為60分。
具體代碼如下:
import java.util.ArrayList; import java.util.HashSet; import java.util.Scanner; public class Main { public static String start, end; public static int x1, y1; //起始就空格狀態start中的空格子坐標 public static int[][] move = {{-1,0},{1,0},{0,-1},{0,1}};//表示分別向上、下、左、右移動一步 public static HashSet<String> set = new HashSet<String>(); //用於存放每次移動空格子后的結果,用於判重 static class Move { //內部類,存放空格子移動一步后的結果 public int x; //空格子位置橫坐標 public int y; //空格子縱坐標移動步數 public int step; //記錄最終 public String temp; //當前九宮格狀態 public Move(int x, int y, int step, String temp) { this.x = x; this.y = y; this.step = step; this.temp = temp; } } public void bfs() { for(int i = 0;i < start.length();i++) { //尋找九宮格初始狀態空格子的位置 if(start.charAt(i) == '.') { x1 = i / 3; y1 = i % 3; } } ArrayList<Move> list = new ArrayList<Move>(); list.add(new Move(x1, y1, 0, start)); set.add(start); while(!list.isEmpty()) { Move now = list.get(0); list.remove(0); if(now.temp.equals(end)) { //當前狀態為最終狀態時,直接退出 System.out.println(now.step); return; } for(int i = 0;i < 4;i++) { //四種行走方案 int x = now.x + move[i][0]; int y = now.y + move[i][1]; if(x < 0 || x > 2 || y < 0 || y > 2) //出現九宮格越界 continue; int step = now.step + 1; char n = now.temp.charAt(x * 3 + y); //獲取當前行走的新位置字符 String temp0 = now.temp; temp0 = temp0.replace(n, '-'); //交換'.'字符和n字符 temp0 = temp0.replace('.', n); temp0 = temp0.replace('-', '.'); if(!set.contains(temp0)) { //判定當前行走結果是否已經行走過 set.add(temp0); list.add(new Move(x, y, step, temp0)); } } } System.out.println("-1"); return; } public static void main(String[] args) { Main test = new Main(); Scanner in = new Scanner(System.in); start = in.next(); //九宮格的初始狀態 end = in.next(); //九宮格的最終狀態 test.bfs(); } }
參考資料: