C 用回溯遞迴解決「八皇后」問題

2021-06-21 05:52:14 字數 2480 閱讀 3912

在很早以前,我曾經用c++寫過一篇使用回溯法來生成隨機數獨的部落格。這一次,考慮到這是一系列關於c#的部落格,所以利用c#的一些特點,來解決著名的「八皇后」問題。

在迭代過程中,不停進行嘗試,如果不行則退回來,換一條路走,這就是「回溯法」的基本思想。

在本例中,基本演算法如下:先遍歷棋盤的每一行,在每一行的第乙個位置放乙個皇后,接下來遍歷每一列,尋找下乙個皇后的位置;一旦找到合適的位置,則把下乙個皇后放上去;然後再尋找其下一列放皇后的位置。如果某一列不存在可以放皇后的位置(也就是「無解」的情況),則將前一步的皇后拿掉,回到前一步尋找下乙個放皇后的位置。

例如,對於以下的情況,我們無法在f列再放入乙個皇后,問題「無解」,此時我們就要將e4的皇后拿走,從e5、e6、e7、e8來遍歷可以放皇后的位置。拿走e4皇后的這個行為就叫做「回溯」——我們試過了不行,所以就返回換乙個條件重新試。

遞迴是不斷呼叫自身的過程。其流程圖大致如下所示:

既然是用c#來實現演算法,那麼就要用到物件導向的思維,而不是c語言中面向過程的思維。在本例中,我們可以看成,我們在「棋盤」上放「皇后」,可以將棋盤和皇后設計為類。棋盤的作用是,用回溯法往自身上面放「皇后」物件,皇后的作用是,記錄自身所在的棋盤位置,以及判斷是否與其它皇后相衝突。

以下是queen類(queen.cs)的源**:

using system;

namespace eightqueen

public int y

public queen(int _x, int _y)

public bool hascollision(queen otherqueen)

public static bool hascollision(queen queen1, queen queen2)

public override string tostring()

, y: ", x, y);}}

}

我們可以用queen.hascollision來判斷兩個queen類是否相衝突(是否在相同橫、豎或斜線上),判斷方法十分簡單,如果兩個皇后的x座標相同,或者y座標相同,或者兩個皇后的x座標之差的絕對值與y座標之差的絕對值相同,則說明它們是相衝突的。

接下來是棋盤類,它用於存放皇后。以下是棋盤類checkerboard.cs的源**:

using system.collections.generic;

using system.text;

namespace eightqueen

public int[,] settlequeen()

private bool settlenext(listqueens, int x)

else

}if (!hascollision)}}

if (!hassettled)

return true;}}

if (queens.count == size)

return true;

}private int[,] toresultmap(ienumerablequeens)

}//將皇后的位置標記為1

foreach (var queen in queens)

return result;

}public static string resultmaptostring(int[,] resultmap)

}return sb.tostring();}}

}

棋盤類在例項化的時候可以接入乙個size引數,表明是棋盤的大小。在設計時,為了解決這一類問題,不應當把棋盤的大小限定為8x8。queens儲存的是某乙個解中的queen物件組,通過toresultmap方法,傳入queens,可以得到乙個矩形陣列int[,],元素總數是size * size。陣列表示的是乙個棋盤,如果某位置沒有皇后,則為0,某位置放了皇后,則為1。如果你覺得這樣不夠直觀,可以用resultmaptostring將這個矩形陣列以文字的形式返回。

下面是程式的入口program.cs:

using system;

namespace eightqueen

console.writeline("共組解。", results.length);

console.readkey(true);}}

}

首先例項化乙個棋盤checkerboard,大小為8*8。通過呼叫checkerboard.settlequeen來得到所有解,通過遍歷所有解,呼叫checkerboard.resultmaptostring方法將所有解輸出,最後輸出解的總數。

在此我們已經看出物件導向程式設計的好處了。整個程式一目了然,非常簡單、清晰。

事實上,只要棋盤的大小≥4,就存在解,大家可以去試一試。

用回溯法解決八皇后問題 C語言

問題描述 要求在8x8的西洋棋棋盤上放入八個皇后,使得任意兩個皇后不能處於同一列,同一行,同一條斜線上。演算法思路 1 判斷皇后之間有沒有衝突,要引入四個量 row 行號,也對應於皇后的編號 column 列號 slash 斜線方向 bslash 反斜線方向 2 由棋盤的布局可以發現,在斜線方向上有...

遞迴回溯解決八皇后問題

問題引入 解決思路 先放置第乙個皇后在第一行遍歷,確定第乙個皇后的列,然後利用遞迴放置下乙個皇后到下一行,並且放置途中需要判斷是否與之前放置的有衝突,直到8個皇后放置完畢,這就是一種解法,然後回溯,回到第8行繼續遍歷看是否有其它解法,如果沒有就繼續回溯到第七行遍歷,有的話就用遞迴找到下一行皇后放置的...

八皇后問題(遞迴,回溯)

八皇后問題是乙個以西洋棋為背景的問題 如何能夠在 8 8 的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題 這時棋盤的大小變為n n,而皇后個數也變成n。當且僅當 n 1 或...