[藍橋杯][歷屆試題]九宮重排
阿新 • • 發佈:2018-12-09
如下面第一個圖的九宮格中,放著 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);
}
}