標準的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;
}
}