八皇后問題,是一個古老而著名的問題,是回溯算法的典型案例。
問題的內容是在國際象棋棋盤上(8*8),放置八個皇后并使其不能互相攻擊。
核心在于皇后的規則:任意兩個皇后都不能處于同一行、同一列或同一斜線上。
之前寫過一次八皇后算法以實現功能為目標,故而顯得代碼冗雜而可讀性低,此次將主要代碼限制在20行。
重寫前的算法
想法依舊是通過遞歸行的方式來解決問題:
第一行取八個不同的皇后位置,并依次向下遞歸調用第二行(即每個位置取一次)
第二行也取八個不同的皇后位置,并判斷是否滿足不能互相攻擊的原則,滿足的再次向下遞歸調用第三行
直到最后一行處理,滿足條件的取出來即八皇后問題的解法。
使用C#實現的效果:
image.png
接下來是用C#實現的代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace test {
class Program {
const int COUNT = 8;
static int anser = 0;
static void Main(string[] args) {
Search(0, new List<int>(), new List<int>());
Console.WriteLine("八皇后問題的解法有: " + anser + " 種。");
Console.ReadLine();
}
static void Search(int line, List<int> x, List<int> y) {
for (int i = 0; i < COUNT; i++) {
for (int c = 0,r = 0; c < x.Count + (x.Count == 0 ? 1 : 0); c++) { //只判斷y -- 用List.foreach
if (x.Count != 0 && i != y[c] && Math.Abs(x[c] - line) != Math.Abs(y[c] - i)) {
r++; //要判斷結果集x,y中的每一個,都符合才行
}
if (r == y.Count && r == 7)
anser++;
if (y.Count == 0 ||r == y.Count && r != 7) {
List<int> tx = x.ToList(); List<int> ty = y.ToList();
tx.Add(line); ty.Add(i);
Search(line + 1, tx, ty);
}
}
}
}
}
}