芜湖,今天的困难题也做出来了!!!和昨天一样,缓存所有的可能,然后直接查询即可,查得到返回对应的值,查不到返回-1;
思路
因为从状态2到状态1需要的滑动次数和从状态1到状态2需要的滑动次数相等,所以从123450开始滑动,记录所有的可能性和对应的次数,然后每次查询即可。
为了方便计算,将二维数组转化为字符串进行操作。
试验得出共有359种可能,最大的移动次数为21次。
算法步骤:
- 首先把数组转为字符串;
- 因为只有0的索引在0-2才可以向下移动、在3-5才可以向上、在不为0和3才可以向左、在不为2和5才可以向右;
- 因为map是实时变化的,所以为了避免map变化引起计算的错误,实验indicate指明当前计算的层次,map中的key存储可能的字符串,value存储需要的次数;
- 在得到所有可能性后,首先把要检测的数组转为字符串,然后查询其是否在map在,在的话则返回对应的value,否则返回-1;
代码
class Solution {
static Map<String, Integer> map_slid;
public void preCount()
{
Map<String, Integer> map_slid1 = new ConcurrentHashMap<>();
String str = "123450";
map_slid1 = new ConcurrentHashMap<>();
map_slid1.put(str,0);
int count = 1;
int indicate = 0;
while(count<360)
{
for (String i : map_slid1.keySet())
{
if (map_slid1.get(i)==indicate)
{//获取0的位置
int index = i.indexOf('0');
int step = map_slid1.get(i);
//判断四个方向是否可以进行交换
//上
if (index>2)
{
String ss = i.substring(0,index-3) + '0' + i.substring(index-2,index) + i.charAt(index-3);
if (index+1<6)
ss += i.substring(index+1,6);
if (!map_slid1.containsKey(ss))
{
map_slid1.put(ss,step+1);
count++;
}
}
//下
if (index<3)
{
String ss = i.substring(0,index) + i.charAt(index+3) + i.substring(index+1,index+3) + '0';
if (index+4<6)
ss += i.substring(index+4,6);
if (!map_slid1.containsKey(ss))
{
map_slid1.put(ss,step+1);
count++;
}
}
//左
if ((index!=0) && (index!=3))
{
String ss = i.substring(0,index-1) + '0' + i.charAt(index-1);
if (index+1<6)
ss += i.substring(index+1,6);
if (!map_slid1.containsKey(ss))
{
map_slid1.put(ss,step+1);
count++;
}
}
//右
if ((index!=2) && (index!=5))
{
String ss = i.substring(0,index) + i.charAt(index+1)+ '0';
if (index+2<6)
ss += i.substring(index+2,6);
if (!map_slid1.containsKey(ss))
{
map_slid1.put(ss,step+1);
count++;
}
}}
}
indicate++;
}
map_slid=map_slid1;
}
public int slidingPuzzle(int[][] board) {
//问题可以简化为--先把所有的可能性计算出来,直接进行匹配即可
preCount();
String input = "";
for (int[] i : board)
for (int j : i)
input += String.valueOf(j);
return map_slid.get(input)==null?-1:map_slid.get(input);
}
}