2016-09-30 52 views
1

我寫了一個N皇后拼圖的Java小算法(用c * c棋盤)。你會發現我的遞歸方法的代碼。遞歸N皇后:缺少解決方案

它沒有找到所有的解決方案。

什麼我的功能

的想法是讓中的主要方法,我的功能的第一個電話給它王后的最大數量,直到找到解決方法,沒有任何女王和這些新的棋盤-queen的座標:x = 0,y = 0。

該功能將通過棋盤。對於每個方塊,它測試是否可以放置皇后(0; 0)(即:無威脅)。女王(0; 0)可以放置?那麼,我們這樣做(修改棋盤),我們稱之爲函數(遞歸調用)。這個遞歸調用是通過「最大數量的皇后-1」,修改後的棋盤和「新皇后的y + 1」(稍微複雜一些)完成的。

與N實測值溶液= 4和C = 4(通常有兩種解決方案...!)

& & Q &

Q & & &

& & & Q

& Q & &

我的功能

private static void setQueen(int nb_queens, ArrayList<ArrayList<Boolean>> chessboard, int x, int y, ArrayList<ArrayList<ArrayList<Boolean>>> solutions) { 
    if (nb_queens == 0) { // If there isn't any queen remaining, it means we found a solution 
     drawChessboard(chessboard); 
     solutions.add(chessboard); 
    } 

    for(int i = x; i < chessboard.size(); i++) { 
     for (int z = y; z < chessboard.get(i).size(); z++) { 
      if(!canBePlaced(i, z, chessboard)) { 
       chessboard.get(z).set(i, true); // On peut donc placer cette reine(x;y) et on le fait 
       setQueen(nb_queens-1, chessboard, i+1, 0, solutions); 
       chessboard.get(z).set(i, false); 
      } 
     } 
    } 

} 

舊代碼的近期代碼

private static void setQueen(int nb_queens, ArrayList<ArrayList<Boolean>> chessboard, int x, int y, ArrayList<ArrayList<ArrayList<Boolean>>> solutions) { 
    if (nb_queens == 0) { 
     drawChessboard(chessboard); // Il n'y a plus de reine à placer => on dessine cette solution 
     solutions.add(chessboard); 
    } 

    for(int i = x; i < chessboard.size(); i++) { 
     for (int z = y; z < chessboard.get(i).size(); z++) { 
      if(!isAQueenAlreadyPresent(i, z, chessboard)) { 
       chessboard.get(z).set(i, true); // On peut donc placer cette reine(x;y) et on le fait 
       setQueen(nb_queens-1, chessboard, i, (z+1 >= WIDTH) ? 0 : z+1, solutions); 
       chessboard.get(z).set(i, false); 
      } 
     } 
    } 

} 
+0

它是否找到任何解決方案?你會得到什麼結果?另外,把'isAQueenAlreadyPresent(i,z,棋盤)',它不應該有問題,但誰知道。此外,同時使用遞歸和迭代是不是真的有用... – Asoub

+0

我編輯OP顯示結果:) –

+0

啊是的,現在我明白了爲什麼遞歸和迭代當然。但它似乎實際上缺乏很多結果,難道不會有更多?像這些解決方案的對比?像&& Q &&&&Q&它與您的第一個結果是對稱的。 – Asoub

回答

1

哦,對了,那是因爲你怎麼稱呼遞歸,你做setQueen(nb_queens-1, chessboard, i, z+1, solutions);z+1部分是問題所在,它總是會在您放置在全局板上的第一個皇后右側找到解決方案。

編輯:啊你之前找到它了,很好。

因此,問題在於for循環充當if(z>=y),因爲它起始於y。當i = x(閱讀第一行)時沒關係,但當i > x時沒有。所以一個簡單的解決方法是在第一個for循環之後放y = (i == x) ? y : 0

甚至有更清潔的解決方案,就像使用單個索引遍歷整個棋盤一樣。

我還建議你重命名你的參數爲startX和startY(而不是x和y,你可以在循環中使用x和y來更清晰)。編輯2:由於遊戲規則,在同一行上永遠不會有女王,所以你可以進行遞歸調用,如setQueen(nb_queens-1, chessboard, i+1, 0, solutions);i+1,因爲你直接從下一行開始)。因此,您甚至可以從setQueen方法中刪除int y參數,並始終以0開始z loop

+0

如果我寫:'int new_z =(z + 1> = WIDTH)? 0:z + 1;'然後用'new_z'(而不是'z')進行遞歸調用,看起來有些解決方案在n = 4和c = 4時仍然丟失。我應該找到2個解決方案,而我只有一個解決方案。你知道爲什麼嗎 ? –

+0

你可以通過執行for(int i = 0; ..'和'for(int z = 0; ..')來輕鬆地消除這個問題。你非常醜陋,並且複雜度爲n^3(wrighting a更好的解決方案) – Asoub

+0

所以你認爲我不能讓我的'I,Z = a_parameter'在我的兩個'for'? –