1. 程式人生 > 實用技巧 >JDK之ConcurrentLinkedQueue的Bug

JDK之ConcurrentLinkedQueue的Bug

回溯演算法——八皇后

什麼是八皇后??
在8×8格的國際象棋上擺放8個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。
什麼是回溯??
回溯搜尋是深度優先搜尋(DFS)的一種,回溯法通俗的將其採用的思想是“一直向下走,走不通就掉頭”。
我們一般在求解八皇后問題的時候說使用的是回溯法,本質也是深搜。

思路
將第一行的皇后放在第一列以後,第二行的皇后放在第一列已經會產生攻擊。這時候不必繼續放第三行的皇后,而將第二行的皇后到第二列,繼續攻擊,放入第三列,不攻擊了才開始進入第三行。如此可依次放下1-5行的皇后。將每個皇后能攻擊到的位置檢查之後,發現第六行的皇后無處安身。這時回溯到第五行的皇后,將其位置由第4列調整為第8列,進入第六行,發現皇后依然無處安身,再次回溯。此第五行已經列舉完所有情況,回溯至第四行,將其由第2列移至第7列,再進入下一行繼續。按此演算法流程最終找到下圖的解,成功在棋盤裡放下了8個“和平共處”的皇后。

回溯演算法求解此問題的思路是:產生攻擊就換列,沒有就換行,不能擺放時回溯,能來到不存在的第九行說明此時前八行的擺放結果是答案。
在這裡插入圖片描述

#include<stdio.h>
#include<math.h>

int a[9],book[9],sum=0;

//a陣列的下標表示行,裡面存放的數字表示列
//book陣列用來標記這一列是否放下了皇后
//sum用來對可行的放置方法基計數

void dfs(int step);//step表示第幾行

int main() {
	dfs(1);//從第一行開始;
	printf("%d", sum);
}

void dfs(int
step) { if (step == 9) {//來到第九行說明八行已經放完 sum++;//計數 return;//回溯 } for (int i = 1; i <= 8; i++) {//i表示列 if (book[i] == 0) {//book[i]為零表示這一列沒有放下皇后 a[step] = i;//在(step,i)處放下皇后 /*檢測剛剛放下的皇后是否會與之前的皇后衝突,即檢測對角線*/ int flag = 1; for (int j = 1; j <step; j++) if (abs(a[step] - a[j]) == abs(step -
j))//當位於對角線上的皇后的橫縱之差的絕對值相等(y=x或y=-x,懂吧) flag = 0; /*flag為1時表示不會衝突*/ if (flag) { book[i] = 1; dfs(step + 1);//進入下行 book[i] = 0; } else continue; } } return;//回溯 }