版权声明:啦啦啦,不用于商业的话随便拿,记得带上博客地址http://blog.csdn.net/wjoker https://blog.csdn.net/wjoker/article/details/84071286
0773.滑动谜题
描述
在一个 2 x 3 的板上(board
)有 5 块砖瓦,用数字 1~5
来表示, 以及一块空缺用 0
来表示.
一次移动定义为选择 0
与一个相邻的数字(上下左右)进行交换.
最终当板 board
的结果是 [[1,2,3],[4,5,0]]
谜板被解开。
给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。
实例
输入:board = [[1,2,3],[4,0,5]]
输出:1
解释:交换 0 和 5 ,1 步完成
输入:board = [[1,2,3],[5,4,0]]
输出:-1
解释:没有办法完成谜板
输入:board = [[4,1,2],[5,0,3]]
输出:5
解释:
最少完成谜板的最少移动次数是 5 ,
一种移动路径:
尚未移动: [[4,1,2],[5,0,3]]
移动 1 次: [[4,1,2],[0,5,3]]
移动 2 次: [[0,1,2],[4,5,3]]
移动 3 次: [[1,0,2],[4,5,3]]
移动 4 次: [[1,2,0],[4,5,3]]
移动 5 次: [[1,2,3],[4,5,0]]
输入:board = [[3,2,4],[1,5,0]]
输出:14
提示
board
是一个如上所述的 2 x 3 的数组.board[i][j]
是一个[0, 1, 2, 3, 4, 5]
的排列.
题解
- 本题是一个广度优先搜索,重点在于
-
- 当前状态
- 下一状态
- 判断是否到过本状态
- 结束判断
slidingPuzzle
中,stateTable
用于存放已经到达过的状态和到达时的步数;stateQueue
用于实现广度优先搜索- 将输入的数组状态表示为字符串状态
- 将初始状态存入
table
和queue
此时步数为0 - 当
queue
不空时, -
- 获取
queue
最上的状态 - 若该状态为结束状态则返回
table
中存的步数 - 否则获取该状态可以到达的所有状态 (
saveState
中实现) - 判断这所有状态是否已经到达过,若没有则步数
+1
存入table
和queue
- 获取
public static int slidingPuzzle(int[][] board) {
HashMap<String,Integer> stateTable = new HashMap<>();
Queue<String> stateQueueq = new LinkedList<>();
char[] chars = new char[6];
chars[0] = (char) (board[0][0] + '0');
chars[1] = (char) (board[0][1] + '0');
chars[2] = (char) (board[0][2] + '0');
chars[3] = (char) (board[1][0] + '0');
chars[4] = (char) (board[1][1] + '0');
chars[5] = (char) (board[1][2] + '0');
String state = new String(chars);
((LinkedList<String>) stateQueueq).add(state);
stateTable.put(state,0);
while (!stateQueueq.isEmpty()){
state = ((LinkedList<String>) stateQueueq).pop();
if (state.equals("123450"))
return stateTable.get(state);
saveState(state,stateTable.get(state),stateTable,stateQueueq);
}
return -1;
}
public static void saveState(String state,int nowStep,HashMap<String,Integer> stateTable,Queue<String> stateQueueq){
ArrayList<String> stringArrayList = getAllMoveWay(state);
for(String string:stringArrayList){
if (!stateTable.containsKey(string)){
stateTable.put(string,nowStep+1);
stateQueueq.add(string);
}
}
}
public static ArrayList<String> getAllMoveWay(String state){
int index = state.indexOf('0');
ArrayList<String> list = new ArrayList<>();
char[] chars = state.toCharArray();
if (index == 0){
list.add(getSwapString(0,1,chars));
list.add(getSwapString(0,3,chars));
return list;
} else if (index == 1){
list.add(getSwapString(1,0,chars));
list.add(getSwapString(1,2,chars));
list.add(getSwapString(1,4,chars));
return list;
} else if (index == 2){
list.add(getSwapString(2,1,chars));
list.add(getSwapString(2,5,chars));
return list;
} else if (index == 3){
list.add(getSwapString(3,0,chars));
list.add(getSwapString(3,4,chars));
return list;
} else if (index == 4){
list.add(getSwapString(4,1,chars));
list.add(getSwapString(4,3,chars));
list.add(getSwapString(4,5,chars));
return list;
} else if (index == 5){
list.add(getSwapString(5,2,chars));
list.add(getSwapString(5,4,chars));
return list;
}
return list;
}
public static void swapChar(int i,int j,char[] chars){
if (i == j)
return;
char tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
}
public static String getSwapString(int i,int j,char[] chars){
swapChar(i,j,chars);
String result = new String(chars);
swapChar(i,j,chars);
return result;
}