申明:
八皇后問題沒有被《程式設計之美》收錄,和《重新開始戰鬥16-程式設計之美-判斷鍊錶是否有環》一樣,筆者也在面試時多次遇到這樣的問題,因此在這裡和大家分享。
八皇后遊戲的說明:
問題的提出:八皇后是個古老而有趣的遊戲,是由高斯於2023年首先提出的。要求在西洋棋的棋盤上放置八個皇后,使其不能相互攻擊,即任意兩個皇后不能處於棋盤的同一行、同一列和同一條對角線上。試問有多少種放法?
對於這個問題,對矩陣有點熟悉的同學會發現,在對角線上,(定義a00到ann為右對角線,an0到a0n為左對角線),若aij,apq在右對角線上,其座標
(i,j)
與(p,q)
滿足i-j=p-q
,而對於左對角線,則滿足
i+j=p+q。也許很多同學都可以找到這個關鍵點。然而更重要的是利用這個性質,進行高效簡單的編碼。
也就是說八皇后我們可以用樹去解決,其空間搜尋樹如下圖所示:
說明:圖中節點例如241表達的是3個皇后的位置:第一行第二列,第二行第四列和第三環第一列。採用回溯法,進行深度優先,不斷遍歷樹種節點,遇到不合適的節點進行回溯,直到達到葉子節點,則為乙個可行的擺法。下面先給出具體**,然後在行進說明:
int col[8],left[15],right[15];
int queen[8];
int n=0;
int sum=0;
void generate()
int h,i;
for(h=0;h<=7;h++)
if(col[h]&&left[n+h] && right[n-h+7])
queen[n]=h;
col[h]=false;
left[n+h]=false;
right[n-h+7]=false;
n+=1;
if(n==8)
sum++;
cout<
cout<
n--;
left[n+h]=true;
right[n-h+7]=true;
col[h]=true;
**說明:
col[8]陣列用以記錄8列中,每一列是否有皇后,例如col[6]=true,表示在第6列的某一行,有乙個皇后;
queen[8]陣列表示第i列的皇后所在的行。例如queen[2]=3,表示3行2列有乙個皇后;
n用於表示樹的層數;
sum用於累加路徑條數,即可以擺放的擺法數目。
**的核心——left[15]與right[15]陣列
left[15]陣列:表示左對角線,正如上面的說明,兩個點在做對角線上,其座標之和一樣,那麼left[i]表示,所有(x,y)點,只要滿足x+y=i是否放有皇后的情況。例如在深度優先檢索一條路徑的過程中,第3號皇后的位置為(4,3),此刻,一定標記left[4+3]=true,因此在對於第四號皇后,其位置不能為(3,4),因為3+4=7,(3,4)與(4,3)一定是出於左對角線上!!!在程式中加入這樣的檢索,就有點了貪心的思想在裡面!!!!當在遍歷到樹中的某一層,發下沒有可用的位置,說明該擺法不正確,因此立刻層層返回!!!
注意在返回的過程中,清空col,left,right等陣列,執行n—等操作。保證回到頂層時,各個記錄陣列的狀態彷彿「新的」一樣。
重新開始戰鬥03 程式設計之美 買書問題
問題描述 由於 哈利波特 系列相當暢銷,店長決定通過 活動來回饋讀者。上櫃的 哈利波特 瓶裝本系列中,一共有5卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5 的費用,三卷更多。具體的折扣如下 本數 折扣 2 5 3 10 4 20 5 25 每本書只能享受一種折扣。例如買...
重新開始戰鬥05 程式設計之美 光影切割
問題描述 假設有乙個矩形區域,有若干條直線切割該區域,並且沒有一條直線與y軸平行,且不存在三條 以及3條以上 切割線相交於一點的情況。請問該矩形平面被分割成多少塊。分析 假設一塊矩形區域已經被切割成很多塊,那麼此時再增加一條切割線,新的切割線與其他切割線相交,且有m個交點。那麼新的切割線被分割成m ...
重新開始戰鬥04 程式設計之美 尋找ID問題
問題描述 乙個很大的列表 有10億多個數 這個列表中全是都是id號,正常狀態下每個id都會再列表中出現兩次 都是亂序 1.當有乙個id號丟失時,如何找到這個id號 2.當有兩個id號丟失時,如何找到這兩個id號。解法一 最直觀 申請乙個陣列,這個陣列和id列表一樣大,然後遍歷id列表,每遍歷乙個id...