标准的BFS题,将九宫格哈希以后记录搜索的状态,用Set边搜索边去重,写的代码用了点面向对象的东西
AC代码:
import java.util.*;
public class Main {
//f为初始状态,e为最终状态
static int f[][] = new int[3][3], e[][] = new int[3][3];
//将'.'表示成9这个数字
static int p = 9;
static int dir[][] = {
{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};
public static void main(String[] args) throws CloneNotSupportedException {
String fs, es;
Scanner in = new Scanner(System.in);
int ans;
fs = in.nextLine();
es = in.nextLine();
//将String映射到九宫格
for (int i = 0; i < fs.length(); i++) {
f[i / 3][i - i / 3 * 3] = (fs.charAt(i) == '.' ? p : fs.charAt(i) - '0');
e[i / 3][i - i / 3 * 3] = (es.charAt(i) == '.' ? p : es.charAt(i) - '0');
}
ans = bfs();
System.out.println(ans);
in.close();
}
static boolean check(int x, int y) {
if (x < 0 || x >= 3 || y < 0 || y >= 3)
return false;
return true;
}
static int bfs() throws CloneNotSupportedException {
Queue<qnode> Q = new LinkedList<>();
//Set用于防止重复搜索以前的状态
Set<hnode> S = new HashSet<>();
qnode bqn;
hnode bhn, ehn;
bqn = new qnode(f, 0);
bhn = new hnode(f);
ehn = new hnode(e);
Q.offer(bqn);
S.add(bhn);
while(!Q.isEmpty()) {
qnode tn = Q.element();
Q.remove();
int[][] a = new int[3][];
for (int i = 0; i < 3; i++) {
a[i] = tn.a[i].clone();
}
int cnt = tn.cnt;
int x = 0, y = 0;
boolean flag = false; //cut time
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (a[i][j] == p) {
x = i; y = j;
flag = true;
break;
}
}
if (flag) break;
}
for (int i = 0; i < 4; i++) {
int nx, ny, t;
nx = x + dir[i][0];
ny = y + dir[i][1];
if (check(nx, ny)) {
t = a[nx][ny];
a[nx][ny] = a[x][y];
a[x][y] = t;
hnode thn = new hnode(a);
if (thn.equals(ehn)) {
return cnt + 1; //BFS找到就是最小次数,直接返回
}
if (!S.contains(thn)) {
S.add(thn);
qnode tt = new qnode(a, cnt + 1);
Q.add(tt);
}
t = a[nx][ny]; //debug 换方向要把九宫格先还原
a[nx][ny] = a[x][y];
a[x][y] = t;
}
}
}
return -1;
}
}
//放在Set中的元素
class hnode {
//hash用于HashSet,也用于判等
//把hash值算好存起来,回来直接return,节省时间
int hash;
public hnode() {
}
public hnode(int[][] a) {
int hc = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
hc *= 10;
hc += a[i][j];
}
}
this.hash = hc;
}
@Override
public boolean equals(Object object) {
hnode thn = (hnode)object;
return thn.hash == hash;
}
@Override
public int hashCode() {
return hash;
}
}
//队列中的元素
class qnode extends hnode {
int[][] a; //记录九宫格状态
int cnt; //记录步数
public qnode() {
}
public qnode(int[][] a, int cnt) {
this.a = new int[3][];
for (int i = 0; i < 3; i++) {
this.a[i] = a[i].clone();
}
this.cnt = cnt;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new qnode(a, cnt);
}
}
之前试了试String,不知道是不是因为遍历和ts = ts + others太慢,超时,如果有大神比较清楚瓶颈在哪给说一声,不胜感激!
超时代码:
import java.util.*;
public class Main {
static int p = 9;
static int dir[][] = {
{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};
static String fs, es;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int ans;
fs = in.nextLine();
es = in.nextLine();
ans = bfs();
System.out.println(ans);
in.close();
}
static boolean check(int x, int y) {
if (x < 0 || x >= 3 || y < 0 || y >= 3)
return false;
return true;
}
static int bfs() {
Queue<qnode> Q = new LinkedList<qnode>();
Set<Integer> S = new HashSet<Integer>();
qnode bqn;
bqn = new qnode(fs, 0);
Q.offer(bqn);
S.add(fs.hashCode());
while(!Q.isEmpty()) {
qnode tn = Q.element();
Q.remove();
String m = tn.m;
int cnt = tn.cnt;
int x = 0, y = 0, len = m.length();
int[][] a = new int[3][3];
for (int i = 0; i < len; i++) {
a[i / 3][i - i / 3 * 3] = (m.charAt(i) == '.' ? p : m.charAt(i) - '0');
if (m.charAt(i) == '.') {
x = i / 3;
y = i - i / 3 * 3;
}
}
for (int i = 0; i < 4; i++) {
int nx, ny, t;
nx = x + dir[i][0];
ny = y + dir[i][1];
if (check(nx, ny)) {
t = a[nx][ny];
a[nx][ny] = a[x][y];
a[x][y] = t;
String ts = "";
for (int w = 0; w < 3; w++) {
for (int j = 0; j < 3; j++) {
ts = ts + (a[w][j] == p ? "." : a[w][j]); //debug
}
}
if (ts.equals(es)) {
return cnt + 1;
}
int tshc = ts.hashCode();
if (!S.contains(tshc)) {
S.add(tshc);
qnode tt = new qnode(ts, cnt + 1);
Q.add(tt);
}
t = a[nx][ny]; //debug
a[nx][ny] = a[x][y];
a[x][y] = t;
}
}
}
return -1;
}
}
class qnode {
String m;
int cnt;
public qnode() {
}
public qnode(String m, int cnt) {
this.m = m;
this.cnt = cnt;
}
}