AI -- 回溯法解決四皇后問題


AI -- 回溯法解決四皇后問題


問題描述

在 4*4 的棋盤上無沖突的擺放 4 個皇后,無沖突是指一個皇后所在位置的水平、豎直以及斜線上不能出現其他的皇后,其他的 n 皇后問題以此類推

解決方法

按行來擺放棋子,下一行的擺放滿足於與上一行的棋子沒有沖突,否則就返回上一步走其他的路線,這就是所謂的回溯法

詳細說明

  1. 在第一行有四種可能,選擇第一個位置放上皇后
    enter description here

  2. 第二行原本可以有四種可能擺放,但是第一第二個已經和第一行的皇后沖突了,因此只剩下第三第四個格子了,先選擇第三個格子
    enter description here

  3. 接下來是第三行,根據規則可以看出,第三行已經沒有位置放了,因為都跟第一第二行的皇后沖突,此時返回到第二行第四個
    enter description here

  4. 繼續來到第三行,發現只有第二個滿足條件
    enter description here

  5. 然后發現第四行已經不能放了,只能繼續返回,返回到第一行,開始下一種可能
    enter description here

  6. 按照 1-5 的步驟,可以找到下面的其中一種解法
    enter description here

總而言之,回溯法就是開始一路到底,碰到南牆了就返回走另外一條路,有點像窮舉法那樣走遍所有的路

算法實現

構建二維數組,增加規則,利用遞歸實現回溯效果

# include <stdio.h>
# define N 4 // 可以調整

int count=0;

// 判斷 Q[i][j] 是否存在沖突 
int isCorrect(int i, int j, int (*Q)[N]) {
    
    int s,t;
    // 判斷行 
    for(s=i,t=0; t<N; t++)
        if(Q[s][t]==1 && t!=j)
            return 0;
            
    // 判斷列 
    for(s=0,t=j; s<N; s++)
        if(Q[s][t]==1 && s!=i)
            return 0;
    
    // 判斷左上角 
    for(s=i-1,t=j-1; s>=0&&t>=0; s--,t--)
        if(Q[s][t]==1)
            return 0;
    
    // 右下角 
    for(s=i+1,t=j+1; s<N&&t<N; s++,t++)
        if(Q[s][t]==1)
            return 0;
    
    // 右上角 
    for(s=i-1,t=j+1; s>=0&&t<N; s--,t++)
        if(Q[s][t]==1)
            return 0;
            
    // 左下角 
    for(s=i+1,t=j-1; s<N&&t>=0; s++,t--)
        if(Q[s][t]==1)
            return 0;
            
    return 1;
    
    
    
}

// 遞歸函數,第 i+1 行的遍歷 
void Queue(int i, int (*Q)[N]) {
     
     int j,k;
     
     // 第四行已經遍歷完,打印符合條件的結果,結束 
     if(i==N) {
         
         count++;
         printf("No.%d slove way\n",count);   
         for(k=0;k<N; k++) {
         
             for(j=0; j<N; j++)
                 printf("%-5d", Q[k][j]);
             printf("\n");
             
             //return;
         }
         printf("\n");
              
     }
      
     // 遍歷第 i+1 行的 j+1 列 
     for(j=0;j<N; j++) {
                  
         if(isCorrect(i,j,Q)) {
                              
             Q[i][j]=1;
             Queue(i+1,Q);   // 遍歷下一行 
             Q[i][j]=0;      // 如果下一行不成立,則回溯,重置 0 
         
         }  
     }  
}

int main() {
    
    int Q[N][N];
    int i,j;
    
    // 初始化二維數組並打印 
    for (i=0; i<N; i++) { 
        
        for(j=0; j<N; j++) {
            Q[i][j] = 0;
            printf("%-5d",Q[i][j]);
        }
        printf("\n");
        
    }
    printf("\n");
    Queue(0, Q); // 從第一行開始遞歸 
    printf("solve count is %d\n", count);
    getchar();
    getchar();
    return 0; 

    
    
}

效果展示

N = 4 時,有兩種解法

enter description here

兩種解法

N = 8 時,有 92 種解法

enter description here

92 種解法

然后手賤試了一下 N = 16 的,結果跑了 7-8 分鍾這樣,已經到了第23028 種解法了,第一行還在第一個位置,果斷放棄

enter description here

enter description here


免責聲明!

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



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