[英]Breadth-First Search implementation not Working
我在使用廣度優先搜索算法時遇到問題,我有一種方法可以隨機排列一個從0到8的整數數組。 我還有一個整數m,告訴我哪個數字為空。 規則如下:
我得到了一些數字,例如:
456
782
301
可以說8是空白值,我可以將其與5、7、2和0交換。因為它們緊鄰它。 我必須使用廣度優先搜索來解決這個難題。 這是我到目前為止編寫的代碼:
package application;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Vector;
public class Solution {
/******************************************
* Implementation Here
***************************************/
/*
* Implementation here: you need to implement the Breadth First Search
* Method
*/
/* Please refer the instruction document for this function in details */
public static LinkedHashSet<int[]> OPEN = new LinkedHashSet<int[]>();
public static HashSet<int[]> CLOSED = new HashSet<int[]>();
public static boolean STATE = false;
public static int empty;
public static void breadthFirstSearch(int[] num, int m, Vector solution1) {
int statesVisited = 0;
for(int i : num) {
if(num[i] == m) {
empty = i;
}
}
int[] start = num;
int[] goal = {0,1,2,3,4,5,6,7,8};
int[] X;
int[] temp = {};
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
int pos = empty; // get position of ZERO or EMPTY SPACE
if (compareArray(X,goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate child nodes
CLOSED.add(X);
temp = up(X, pos);
if (temp != null)
OPEN.add(temp);
temp = left(X, pos);
if (temp != null)
OPEN.add(temp);
temp = down(X, pos);
if (temp != null)
OPEN.add(temp);
temp = right(X, pos);
if (temp != null)
OPEN.add(temp);
if(OPEN.isEmpty())
System.out.println("Ending loop");
}
}
}
public static boolean compareArray(int[] a, int[] b) {
for(int i: a)
if(a[i] != b[i])
return false;
return true;
}
public static int[] up(int[] s, int p) {
int[] str = s;
if (p > 3) {
int temp = str[p-3];
str[p-3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] down(int[] s, int p) {
int[] str = s;
if (p < 6) {
int temp = str[p+3];
str[p+3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] left(int[] s, int p) {
int[] str = s;
if (p != 0 && p != 3 && p != 6) {
int temp = str[p-1];
str[p-1] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] right(int[] s, int p) {
int[] str = s;
if (p != 2 && p != 5 && p != 8) {
int temp = str[p+1];
str[p+1] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
此代碼只是立即結束,而從未找到答案。 也許我做錯了什么? 請幫忙。
請注意:這是我對StackOverFlow的第一個問題,因此,如果有人有任何批評,請告訴我,我會立即修復。
首先,您有一個沒有做任何事情的參數, Vector solution
位於:
public static void breadthFirstSearch(int[] num, int m, Vector solution1)
另外,您傳入的是表示為m的零元素的位置,然后將一個局部變量分配給該位置,對我來說似乎毫無意義,如果您要搜索,則無需傳入零位置無論如何。
更新了廣度優先搜索方法:
public static void breadthFirstSearch(int[] num) {
for (int i : num) {
if (num[i] == 0) {
empty = i;
}
}
int[] start = num;
int[] goal = {1, 2, 3, 4, 5, 6, 7, 8, 0};
int[] X;
int[] temp = {};
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
int pos = empty; // get position of ZERO or EMPTY SPACE
if (Arrays.equals(X, goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate child nodes
CLOSED.add(X);
temp = up(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = left(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = down(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = right(X, pos);
if (temp != null) {
OPEN.add(temp);
}
if (OPEN.isEmpty()) {
System.out.println("Ending loop");
}
}
}
}
程序的主要問題是在您的移動方法中, up()
, down()
, left()
, right()
。 您沒有創建陣列的完整副本,因此會導致原始陣列發生修改。
因此,該賦值: int[] str = s;
必須更改為:
int[] str = new int[s.length];
System.arraycopy(s, 0, str, 0, s.length);
這是一個完整方法的示例:
public static int[] up(int[] s, int p) {
int[] str = new int[s.length];
System.arraycopy(s, 0, str, 0, s.length);
if (p > 3) {
int temp = str[p - 3];
str[p - 3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && !CLOSED.contains(str)) {
return str;
} else {
return null;
}
}
旁注 (不是必需的):
數組的某些排列不會導致目標狀態。 這個難題本身總共可以有9!
配置,但實際上只有9!/2
是可解決的。
我編寫了一種算法來檢查拼圖的奇偶性,可以將其作為一種預處理來完成,我使用它來創建用於測試數據的隨機實例。
public boolean isSolvable(int[] puzzle) {
boolean parity = true;
int gridWidth = (int) Math.sqrt(puzzle.length);
boolean blankRowEven = true; // the row with the blank tile
for (int i = 0; i < puzzle.length; i++) {
if (puzzle[i] == 0) { // the blank tile
blankRowEven = (i / gridWidth) % 2==0;
continue;
}
for (int j = i + 1; j < puzzle.length; j++) {
if (puzzle[i] > puzzle[j] && puzzle[j] != 0) {
parity = !parity;
}
}
}
// even grid with blank on even row; counting from top
if (gridWidth % 2 == 0 && blankRowEven) {
return !parity;
}
return parity;
}
對於矢量
您希望能夠打印出達到目標狀態所采用的路徑,我建議為該State
一個類:
private State previousState;
private int[] current;
public State(int[] current, State previousState) {
this.current = current;
this.previousState = previousState
}
public State getPreviouState(){
return previousState;
}
public int[] getCurrentState(){
return currentState;
}
然后,當您擁有目標State
您可以遍歷所有先前的州以查看其走過的路。
State current = GOAL;
while(current != null){
System.out.println(Arrays.toString(current));
current = current.getPreviousState();
}
up(...)方法有錯誤:
你有:
str[p] = str[p-3];
我猜應該是:
str[p] = temp;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.