藍橋杯 歷屆試題 九宮重排 BFS Java

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章