ACM_N皇后問題


N皇后問題

Time Limit: 2000/1000ms (Java/Others)

Problem Description:

在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

Input:

共有若干行,每行一個正整數N≤12,表示棋盤和皇后的數量;如果N=0,表示結束。

Output:

共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。

Sample Input:

1
8
5
0

Sample Output:

1
92
10
解題思路:N皇后問題即任兩個皇后都不能處於同一條橫行、縱行或斜線上。求解這一問題涉及到試探+回溯算法,用遞歸就可以將思路清晰地展現出來。我們在試探的過程中,皇后的放置需要檢查他的位置是否和已經放置好的皇后發生沖突,為此需要以及檢查函數place()來檢查當前要放置皇后的位置,是不是和其他已經放置的皇后發生沖突。假設有兩個皇后被放置在(i,j)和(k,l)的位置上,明顯,當且僅當|i-k|=|j-l| 時,兩個皇后才在同一條對角線上。(1)先從首位開始檢查,如果不能放置,接着檢查該行第二個位置,依次檢查下去,直到在該行找到一個可以放置一個皇后的地方,然后保存當前狀態,轉到下一行重復上述方法的檢索。 (2)如果檢查了該行所有的位置均不能放置一個皇后,說明上一行皇后放置的位置無法讓所有的皇后找到自己合適的位置,因此就要回溯到上一行,重新檢查該皇后位置后面的位置。
AC代碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int queen[15],cnt,n;    //存放各皇后所在的列號,cnt為解個數
 4 bool place(int row){     /* 檢查橫列和對角線上是否可以放置皇后 */
 5     for(int i=0;i<row;++i){ //和已經擺放好的皇后進行比較
 6         if ((queen[i]==queen[row]) || (abs(queen[i]-queen[row])==abs(row-i)))
 7             return false;
 8     }
 9     return true;
10 }
11 void QueenSet(int row){/* 回溯嘗試皇后位置,row為橫坐標 */
12     for(int col=0;col<n;++col){ //首先將皇后放在第0列的位置,對於第一次來說是肯定成立的
13         queen[row]=col;/* 將皇后擺到當前循環到的位置 */
14         if(place(row)){//如果放置成功
15             if(row==n-1)++cnt;/* 如果全部擺好,則解的個數加1 */
16             else QueenSet(row+1);/* 否則繼續擺放下一個皇后 */
17         }//這里遞歸時已經將當前地址壓進棧中
18     }//所以當所在行的所有列不滿足時,便會出棧,即回溯,返回到上一行的下一列
19 }
20 int main(){
21     while(cin>>n && n){
22         cnt=0;//解的個數
23         QueenSet(0);/* 從橫坐標為0開始依次嘗試 */
24         cout<<cnt<<endl;
25     }
26     return 0;
27 }
而杭電hdu2553這題卻需要先打表,不然會超時,題目給出的N最大為10。
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
AC代碼:
#include<bits/stdc++.h>
using namespace std;
int queen[11],num[11],cnt,n,N;    //存放各皇后所在的列號,cnt為解個數,num數組記錄每n個皇后的解
bool place(int row){     /* 檢查橫列和對角線上是否可以放置皇后 */
    for(int i=0;i<row;++i){ //和已經擺放好的皇后進行比較
        if ((queen[i]==queen[row]) || (abs(queen[i]-queen[row])==abs(row-i)))
            return false;
    }
    return true;
}
void QueenSet(int row){/* 回溯嘗試皇后位置,row為橫坐標 */
    for(int col=0;col<n;++col){ //首先將皇后放在第0列的位置,對於第一次來說是肯定成立的
        queen[row]=col;/* 將皇后擺到當前循環到的位置 */
        if(place(row)){//如果放置成功
            if(row==n-1)++cnt;/* 如果全部擺好,則解的個數加1 */
            else QueenSet(row+1);/* 否則繼續擺放下一個皇后 */
        }
    }
}
int main(){
    for(n=1;n<11;++n){
        cnt=0;//解的個數
        QueenSet(0);/* 從橫坐標為0開始依次嘗試 */
        num[n]=cnt;
    }
    while(cin>>N && N)
        cout<<num[N]<<endl;
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM