# Backtracking# Recursion# Greedy# Array

a160 - 祖靈想要下棋!!!!!!!!

🔗 前往 ZeroJudge 原題

題目描述

題目要求找出 N 皇后問題的所有解,並以棋盤的形式輸出。N 皇后問題是指在一個 N x N 的棋盤上放置 N 個皇后,使得任何兩個皇后都不能互相攻擊(即不在同一行、同一列或同一對角線上)。輸出時,用 'x' 表示空格,用 'Q' 表示皇后。最後輸出解的總數。

解題思路

這題使用 backtracking (回溯法) 解決 N 皇后問題。valid_position 函數檢查在給定的位置放置皇后是否安全,即是否與已放置的皇后衝突。put 函數遞迴地嘗試在每一列放置皇后。如果找到一個安全的位置,則繼續遞迴到下一列。如果所有列都放置了皇后,則輸出棋盤並增加解的計數。回溯法通過嘗試所有可能的放置方式,並在發現衝突時回溯到上一步,最終找到所有有效的解。

複雜度分析

  • 時間複雜度: O(N!)。在最壞的情況下,需要嘗試所有可能的皇后放置方式。
  • 空間複雜度: O(N)。主要用於儲存棋盤狀態和遞迴調用堆疊。

程式碼

#include <iostream>
using namespace std;
int n=0,ans=0;
bool space[13][13];
bool valid_position(int r , int c){ 
    for(int i=0;i<n;++i){ 
        if(space[i][c]==1&&i!=r) 
            return 0; 
        else if(space[r][i]==1&&i!=c) 
            return 0; 
        else if(r+i<n&&c+i<n&&space[r+i][c+i]==1) 
            return 0; 
        else if(r+i<n&&c-i>=0&&space[r+i][c-i]==1) 
            return 0; 
        else if(r-i>=0&&c+i<n&&space[r-i][c+i]==1) 
            return 0; 
        else if(r-i>=0&&c-i>=0&&space[r-i][c-i]==1) 
            return 0; 
    } 
    return 1; 
} 
void put(int col){
	for(int j=0;j<n;++j){
		space[col][j]=valid_position(col,j);
		if(space[col][j]==1&&col==n-1){
			for(int ii=0;ii<n;++ii){
				for(int jj=0;jj<n;++jj){
					if(space[ii][jj])
						cout << 'Q';
					else
						cout << 'x';
				}
				cout << "\n";
			}
			++ans;
			cout << "\n";
			space[col][j]=0;
			break;
		}
		else if(space[col][j]==1){
			put(col+1);
			space[col][j]=0;
		}
	}
}
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	while(cin >> n){
		if(n==0)break;
		ans=0;
		for(int i=0;i<13;++i)
			for(int j=0;j<13;++j)
				space[i][j]=0;
		put(0);
		cout << "\n" << ans << "\n";
	}
}

Discussion