首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

八皇后問題深度解析:回溯算法經典實現與C語言代碼詳解

     編輯:關於C語言

八皇后問題是計算機科學與數學領域中最著名的經典問題之一,作為回溯算法的教科書級案例,它不僅展示了遞歸思想的優雅,更蘊含著豐富的算法優化智慧。本文將從問題起源、數學建模、算法設計到代碼實現,為您全方位剖析這個迷人的棋盤謎題。

問題背景與歷史演進

1850年,數學巨匠高斯首次提出:在標準8×8國際象棋棋盤上放置八個皇后,使任意兩個皇后都不在同一行、同一列或同一對角線上。高斯初步估計有76種解法,但1854年柏林象棋雜誌刊登了40種不同解答,後經圖論方法證實共有92種本質不同解法(若考慮旋轉鏡像對稱,則有12種基本解)。

隨著計算機誕生,該問題成為驗證編程語言性能、教學遞歸回溯算法的標準測試案例。維基百科將其推廣為N皇后問題:當且僅當 n=1 或 n≥4 時存在解。

核心約束條件建模

在二維坐標系中,皇后位置 (i, j) 需滿足三大約束:

  • 行約束:同一行僅能有一個皇后 → 通過按行遞歸天然滿足
  • 列約束:同一列不能重複 → 檢查 queen[0..i-1][j]
  • 對角線約束:主對角線 (i-j 固定)、副對角線 (i+j 固定) 不能重複

回溯算法設計思路

採用「逐行放置 + 衝突檢測 + 回溯撤銷」策略:

  1. 從第0行開始,嘗試在每列放置皇后
  2. 調用 check() 驗證列、左上、右上三個方向是否衝突
  3. 若安全則遞歸處理下一行 put(i+1)
  4. 若到達第8行(i≥8),輸出一個完整解
  5. 回溯時將 queen[i][j] 重置為0,繼續嘗試下一列

C語言完整實現代碼

#include <stdio.h>

int queen[8][8];  // 棋盤狀態:1=有皇后,0=空
int m = 1;        // 解法計數器

// 衝突檢測:返回0表示安全,>0表示衝突數
int check(int i, int j) {
    int k = 0, a, b;
    
    // 檢查同列
    for (a = 0; a < i; a++)
        if (queen[a][j] == 1) k++;
    
    // 檢查左上對角線 (i-1,j-1) (i-2,j-2)...
    for (a = i-1, b = j-1; a >= 0 && b >= 0; a--, b--)
        if (queen[a][b] == 1) k++;
    
    // 檢查右上對角線 (i-1,j+1) (i-2,j+2)...
    for (a = i-1, b = j+1; a >= 0 && b < 8; a--, b++)
        if (queen[a][b] == 1) k++;
    
    return k;
}

// 遞歸放置皇后
void put(int i) {
    int j;
    if (i >= 8) {  // 找到一組完整解
        printf("第%d種解法:\n", m++);
        for (i = 0; i < 8; i++) {
            for (j = 0; j < 8; j++)
                printf(queen[i][j] == 1 ? "%d " : "- ", j);
            printf("\n");
        }
        printf("\n");
    } else {  // 逐列嘗試放置
        for (j = 0; j < 8; j++) {
            queen[i][j] = 1;           // 嘗試放置
            if (check(i, j) == 0)      // 安全則遞歸
                put(i + 1);
            queen[i][j] = 0;           // 回溯撤銷
        }
    }
}

int main() {
    put(0);  // 從第0行開始
    return 0;
}

代碼關鍵點解析

1. 二維數組 vs 一維優化

本代碼使用 int queen[8][8] 直觀存儲棋盤,雖空間佔用較大(64字節),但邏輯清晰。進階優化可用一維數組 col[8] 記錄每行皇后列號,空間壓縮至32字節,檢測邏輯改為:

// 一維數組衝突檢測
for (int k = 0; k < row; k++) {
    if (col[k] == col[row] || 
        abs(col[k] - col[row]) == row - k)  // 對角線判斷
        return 0;  // 衝突
}

2. 遞歸終止條件

i >= 8 表示前8行(0-7)均已成功放置,當前調用層級為第9層,此時輸出解法。

3. 回溯的本質

queen[i][j] = 0 是回溯的核心——撤銷當前選擇,讓上層調用繼續嘗試下一列。這體現了深度優先搜索(DFS)的狀態空間樹遍歷特性。

算法複雜度分析

  • 時間複雜度:O(N!) 理論上界,實際剪枝後約 O(N^N) 量級。N=8時僅需檢測約15,720個節點即可找出所有92解。
  • 空間複雜度:O(N²) 二維數組,或 O(N) 一維優化 + 遞歸棧 O(N)。

擴展與變體

  • N皇后通用解:將8替換為變量N,支援任意棋盤大小
  • 位運算優化:用整數位掩碼表示列、主對角線、副對角線佔用,實現O(1)衝突檢測,速度提升數十倍
  • 並行化求解:將搜索樹根節點分配給多線程,適合大規模N值
  • 約束滿足問題(CSP):建模為精確覆蓋問題,用Dancing Links (DLX) 算法求解

教學價值與實戰啟示

八皇后問題不僅是遞歸回溯的入門範例,更展示了狀態空間搜索、剪枝優化、對稱性利用等核心算法思想。實際工程中,類似思想廣泛應用於:

  • 編譯器寄存器分配(圖著色問題)
  • 任務調度與資源分配
  • 電路板佈線與VLSI佈局
  • 數獨求解器、迷宮生成與路徑規劃

掌握八皇后的遞歸回溯模板,即掌握了解決大組合優化問題的通用鑰匙。建議讀者嘗試實現一維數組版、位運算版、乃至DLX版本,體會算法優化的層層遞進之美。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved