回溯法解決N皇后問題(java實現)
阿新 • • 發佈:2019-02-01
1.簡單介紹回溯法思路,就是將所有的結果變成一棵樹,從樹的結點開始訪問,採用深度優先策略,從樹的根結點開始訪問,如果滿足條件,繼續訪問下一層,如果不滿足條件,返回上一個結點,繼續訪問其它結點。重複操作。
2. 對於N皇后問題,我特意做了一張圖片。首先放置第一列,有四种放法,如果第一列,放置在第一個,再放置第二列,也有四种放法,很顯然,第二列的第一種放法,不符合條件,這種放法下面所的子樹也就不必訪問了,節省了訪問時間,然後繼續第三列,第四列。就可以得到結果了。
3.這裡的程式碼是參考網上的,不記得是部落格地址是哪了,不好意思。原始碼是用C語言實現的,我改成了java。參考如下
package com.bc;
public class huanghou {
public static int Q=4; //代表四皇后
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] dp=new int[Q][Q];
int i,j;
//初始化
for(i=0;i<Q;i++)
{
for(j=0;j<Q;j++)
{
dp[i][j]=0 ;
}
}
que(0,dp);
}
private static void que(int m, int[][] dp) {
// TODO Auto-generated method stub
if(m==Q){//遞迴結束條件
for(int i=0;i<Q;i++)
{
for(int j=0;j<Q;j++)
{
System.out.print(dp[i][j]+" " );
}
System.out.println("\n");
}
System.out.println("**********************");
}
//遞迴計算
for(int i=0;i<Q;i++)
{
if (isCorrt(i,m,dp)) {
dp[i][m]=1;
que(m+1, dp);
dp[i][m]=0;
}
}
}
//判斷這個位置能不能放皇后
private static boolean isCorrt(int i, int j, int[][] dp) {
// TODO Auto-generated method stub
int s, t; //s代表行,t代表列
for(s=i,t=0; t<Q; t++)
if(dp[s][t]==1 && t!=j)
return false;//判斷行
for(t=j,s=0; s<Q; s++)
if(dp[s][t]==1 && s!=i)
return false;//判斷列
for(s=i-1,t=j-1; s>=0&&t>=0; s--,t--)
if(dp[s][t]==1)
return false;//判斷左上方
for(s=i+1,t=j+1; s<Q&&t<Q;s++,t++)
if(dp[s][t]==1)
return false;//判斷右下方
for(s=i-1,t=j+1; s>=0&&t<Q; s--,t++)
if(dp[s][t]==1)
return false;//判斷右上方
for(s=i+1,t=j-1; s<Q&&t>=0; s++,t--)
if(dp[s][t]==1)
return false;//判斷左下方
return true;
}
}
4.總結:其實感覺回溯法有類似窮舉,把所有的結果都列出來。只是回溯法,把結果變成了一棵樹,如果在某個結點的時候,已經不滿足條件了,那後面的選擇肯定不滿足條件,這樣就節省了遍歷所有的結果的時間。提高了效率。