Följande kod fungerar bra men tar för mycket tid. placeQueens
kräver också mycket tid. Programmet tar 5-10 sekunder.
public class EightQueen { public static void startSimulation(){ long startTime = System.currentTimeMillis(); char[] board; // Create an array // Repeat while queens are attacking do { // Generate a board board = getNewBoard(); // Place eight queens placeQueens(board); } while (isAttacking(board)); // Display solution print(board); long endTime = System.currentTimeMillis(); System.out.println(endTime - startTime); } /** placeQueens randomly places eight queens on the board*/ public static void placeQueens(char[] board) { int location; for (int i = 0; i < 8; i++) { do { location = placeQueens(); } while (isOccupied(board[location])); board[location] = "Q"; } } /** placeQueens randomly places one queen on the board */ public static int placeQueens() { return (int)(Math.random() * 64); } /** isAttacking returns true if two queens are attacking each other */ public static boolean isAttacking(char[] board) { return isSameRow(board) || isSameColumn(board) || isSameDiagonal(board); } /** isSameRow returns true if two queens are in the same row */ public static boolean isSameRow(char[] board) { int[] rows = new int[8]; for (int i = 0; i < board.length; i++) { if (isOccupied(board[i])) { rows[getRow(i)]++; } if (rows[getRow(i)] > 1) return true; } return false; } /** isSameColumn returns true if two queens are in the same column */ public static boolean isSameColumn(char[] board) { int[] columns = new int[8]; for (int i = 0; i < board.length; i++) { if (isOccupied(board[i])) { columns[getColumn(i)]++; } if (columns[getColumn(i)] > 1) return true; } return false; } /** isSameDiagonal returns true if two queens are on the same diagonal */ public static boolean isSameDiagonal(char[] board) { for (int i = 0; i < board.length; i++) { if (isOccupied(board[i])) { for (int j = 0; j < board.length; j++) { if (isOccupied(board[j]) && Math.abs(getColumn(j) - getColumn(i)) == Math.abs(getRow(j) - getRow(i)) && j != i) { return true; } } } } return false; } /** isOccupied returns true if the element in x is the char Q */ public static boolean isOccupied(char x) { return x == "Q"; } /** getNewBoard returns a char array filled with blank space */ public static char[] getNewBoard() { char[] board = new char[64]; for (int i = 0; i < board.length; i++) board[i] = " "; return board; } /** print displays the board */ public static void print(char[] board) { for (int i = 0; i < board.length; i++) { System.out.print( "|" + ((getRow(i + 1) == 0) ? board[i] + "|\n" : board[i])); } } /** getRow returns the row number that corresponds to the given index */ public static int getRow(int index) { return index % 8; } /** getColumn returns the column number that corresponds to the given index */ public static int getColumn(int index) { return index / 8; } }
Kommentarer
Svara
Precis som bogosort kommer aldrig att vara en snabb sorteringsalgoritm. Din ”kasta bort styrelsen och slumpmässigt placera N nya drottningar” -lösningen kommer aldrig att bli snabbare än de 5 till 10 sekunderna.
Ändå gjorde det mig glad att se att den faktiskt hittar en lösning något konsekvent. Och själva frågan består också bra, så jag tycker att den förtjänar ett svar.
Som CiaPan redan föreslog i en kommentar är ett mycket bättre sätt att lösa n-drottningsproblemet med backtracking. Mitt snabba testprogram med detta tillvägagångssätt löser 8-drottningarna på 1 millisekund (eller mindre). (Och a 20-drottningarna på 50 ms).
Men ”Återställ och slumpmässigt placera n nya drottningar” är intressant att se, så låt oss lägga till en större förbättring för att påskynda lösning.
/** placeQueens randomly places eight queens on the board*/ public static void placeQueens(char[] board) { int location; for (int i = 0; i < 8; i++) { do { location = placeQueens(i); } while (isOccupied(board[location])); board[location] = "Q"; } } /** placeQueens randomly places one queen on the board */ public static int placeQueens(int row) { return row * 8 + (int)(Math.random() * 8); }
Den här lilla förändringen här fick tiden tills lösningen konsekvent blev under 100 ms. Varför? Eftersom detta minskar sökutrymmet från O (n³) till O (n²). Anledningen till att detta fungerar är att det i alla lösningar finns exakt 1 drottning på varje rad. Så jag genererar en slumpmässigt för varje rad istället för på hela tavlan.
Kommentarer
- Tack för det fantastiska svaret, men det ’ s verkar som att jag redan har slutat snabbt en men ändå har problem med set random queen .
- Det finns en annan punkt som är värt att överväga: @IbrahimAli gjorde inte ’ t säga vad hans mål egentligen är, att hitta något giltigt arrangemang eller alla giltiga arrangemang av 8 drottningar. Systematisk sökning i en slinga gör det senare (retur n alla möjliga lösningar, och var och en exakt en gång), medan slumpmässig generering inte kan (kan mycket väl upprepa svar och vi vet aldrig om det hittade alla möjligheter; med dålig RNG-kvalitet kan det till och med vara omöjligt att hitta några).
- @CiaPan I ’ jag tänker på
n
position förn
booleska helt enkelt skapar jag en boolean array och använder den ’ s index beroende på slumpmässigt drottningar, varje genererad drottning som jag ställer in olagligt index till falskt i den booleska matrisen som kommer att vara kort mycket tid. - @Imus Du behöver ’ t behöver
do – while
loop, eftersom varjeplaceQueens(i)
anropas avfor (int i = 0; i < 8; i++)
-slingan tilldelar en position i en separat rad, Därför är kollisioner omöjliga och att testa för dem är slöseri med tid. - Aha sann CiaPan. Väl prickig. Jag gjorde bara den minsta ändringen för att generera en på varje rad i den ursprungliga koden. Det är ’ varför jag just skickade in det
i
till metoden. Jag märkte också den nu överflödiga kontrollen, men det ger dig bara mindre än ett millisekund när du hittar lösningen. Så du kan ’ verkligen inte se skillnaden.
main()
-funktionen?main()
!!startSimulation()
vara huvudfunktionen? Om så är fallet kan du kalla detmain()
istället.