1. 程式人生 > >[藍橋杯][歷屆試題]九宮重排

[藍橋杯][歷屆試題]九宮重排

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

在這裡插入圖片描述

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

輸入
輸入第一行包含九宮的初態,第二行包含九宮的終態。

輸出
輸出最少的步數,如果不存在方案,則輸出-1。

樣例輸入
12345678.
123.46758

樣例輸出
3

基本思想在於:
使用bfs廣度搜索,借用佇列實現。
1)使用queue儲存當前可能移動的所有狀態
2)依次出佇列再繼續判斷接下來的所有可能狀態,插入佇列
3) 對待每次的變化後的String,都需要儲存當前的移動步數,這裡用hashmap實現,每個鍵String 對應 一個值Integer(這個字串的步數)
4)判斷每一條變化的String是否與結果一致,若一致,則輸出結果,否則繼續
5)若直到最後的佇列為空都沒有結果,則輸出-1

import java.util.HashMap;
import java.util.LinkedList;
import java.util.
Queue; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str1 = sc.nextLine(); String str2 = sc.nextLine(); int result = -1; HashMap<String, Integer> map = new HashMap<String,
Integer>
(); //用來存放移動的每一次String,以及當前步數,能夠用來查重 Queue<String> queue = new LinkedList<String>(); //通過Queue實現廣度遍歷,使得儲存的順序是相鄰的可移動方式 map.put(str1, 0); queue.offer(str1); int[] move = {-3,+3,-1,1}; //九宮格中所有的移動方式 while(result==-1) { str1 = queue.poll();if(null==str1) break; int temp = str1.indexOf("."); //獲取當前佇列中String的“.”的位置 for(int i=0;i<=3;i++) { int p = temp+move[i];//計算移動的步數 if((p==2&&temp==3)||(p==3&&temp==2)||(p==5&&temp==6)||(p==6&&temp==5)) continue; //排除012345678的九宮格中 3和2;5和6的錯誤移動 if(p>=0&&p<=8) { //判斷移動是否超出邊界 String change = str1; char temp_char = change.charAt(p); change = change.replace('.', '0'); change = change.replace(change.charAt(p), '.'); change = change.replace('0',temp_char); //以上是移動一次的結果 if(change.equals(str2)) { //判斷是否相同,若相同,則返回結果 result = map.get(str1)+1; } if(!map.containsKey(change)) { //判斷map中是否已經存在這個字串,若沒有,則存入 map.put(change, map.get(str1)+1); queue.offer(change); } } } } System.out.println(result); } }