Java
import java.util.Random; public class LVQueen { // 問題規模 static int SIZE = 8; // 隨機數發生器 static Random rnd = new Random(SIZE); // 解向量 static int[] queen = new int[SIZE]; private static boolean check(int row) { for (int i = 0; i < queen.length && i != row; i++) { if (queen[i] == queen[row] || i - queen[i] == row - queen[row] || i + queen[i] == row + queen[row]) { return false; } } return true; } private static boolean queensLV() { int row = 0; int count = 1; while ((row < SIZE) && (count > 0)) { count = 0; int j = 0; for (int column = 0; column < SIZE; column++) { queen[row] = column; if (check(row)) { if (rnd.nextInt(++count) == 0) { j = column; // break;//有break如果第一此找到合適的列place(k)滿足,那么此時random(1)==0恆成立,遇到下面的break,就把皇后放置在這個位置。如果這種放置皇后的方案不可行,下次循環還會執行同樣的,故一直循環調不出來找不到方案。即剩下的所有皇后放置不了的可能性增大。 // 沒有break,會一直試探for循環結束。x[k]會在隨機的選擇當前可以放置的位置中for循環最后一個滿足的列。那么后面如果n-1個皇后放置不了的可能性減小。 } } } if (count > 0) { queen[row++] = j; } } return (count > 0); } public static void nQueen() { while (!queensLV()); System.out.println("-----解法--------"); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (queen[i] == j) { System.out.print(" Q "); } else { System.out.print(" . "); } } System.out.println(); } } public static void main(String[] args) { nQueen(); } }
總結一下它的思想,
就是從第一行開始,尋找可以放置的位置,顯然第一行七種擺法都是可以的,隨機抽取一種,擺上去
到第二行的時候,可以擺放的位置少了幾種,從這幾種里面又隨機取一種擺上去
如此循環,但顯然大概率擺放到后面的時候,會發現無解,所以才會有
while (!queensLV());
這么一行,知道碰運氣找到了解才結束。
它和之前的暴利遞歸算法不同之處在於
1.拉斯維加斯算法旨在尋找一個解而非全部解
2.由於不是有序遍歷,所以LV算法效率其實並不高,但是理論上存在比遍歷更快找到解的可能