1. 程式人生 > >n皇后問題--分支限界法

n皇后問題--分支限界法

問題描述

    八皇后問題是一個古老而著名的問題,它是回溯演算法的典型例題,現在用分支限界的演算法來解決這個問題。該問題是十九世紀德國著名數學家高斯於1850年提出的:在8行8列的國際象棋棋盤上擺放著 八個皇后。若兩個皇后位於同一行、同一列或同一對角線上,則稱為它們為互相攻擊。現在要求使這N個皇后不能相互攻擊,即任意兩個皇后都不能處於同一行、同一列或同一對角線上,問有多少種擺法。

在分支限界法中,每一個活結點只有一次機會成為擴充套件節點。活結點一旦成為擴充套件節點,就一次性產出所有兒子節點。在這些所有的兒子節點中,導致不可行解或導致非最優解的兒子節點被捨棄,滿足條件的兒子結點被加入到活結點表中。此後,從活結點表中取下一個結點成為當前擴充套件節點,並重覆上述結點擴充套件過程。這個過程一直持續到我們找到所需的解或者是活性表為空為止。

演算法模板

定義根節點t0為初始化擴充套件節點
根節點t0入隊
while(隊不空)
{
    出隊 --t;
    for (j = r0; j < rn; ++j)
    {
        對t利用規則j發展新節點tj;
        利用限界函式判斷tj是否可行;
        if (可行)
        {
            若是目標解,找到結果,return
            否則,進隊
        }
    }
}
#include <iostream>
#include <queue>

using namespace std;

class Node
{
public:
	Node(int n) : t(0), n(n)
	{
		pos = new int[n + 1];
		for (int i = 0; i <= n; ++i)
		{
			pos[i] = 0;
		}
	}

	Node(const Node& other)
	{
		t = other.t;
		n = other.n;
		pos = new int[other.n + 1];
		for (int i = 0; i <= n; ++i)
		{
			pos[i] = other.pos[i];
		}
	}

	~Node()
	{
		if (pos != NULL)
		{
			delete[] pos;
			pos = NULL;
		}
	}

	bool check(int next);
	int t;//當前已經放置了多少個皇后
	int n;//需要放置多少個皇后
	int *pos; //指向當前已放好的皇后位置,pos[1]代表第1個皇后所放的列數,所放的行數為1,這樣設定可以不用檢查行是否相等
};

bool Node::check(int next)
{
	int i; //表示已經已經放置皇后的行
	for (i = 1; i <= t; ++i)
	{
		int j = pos[i]; //代表已經放置的皇后的列
		//同列
		if (j == next)
		{
			return false;
		}
		//右上角到左下角的對角線
		if ((next - j) == (i - 1 - t))
		{
			return false;
		}
		//左上角到右下角的對角線
		if ((next - j) == (t + 1 - i))
		{
			return false;
		}
	}
	return true;
}

class Queen
{
public:
	Queen(int x) : n(x), ansNum(0){}
	int QueenArrange(); //排列皇后的方式
private:
	int n; //皇后數量
	int ansNum; //n皇后解的數量
};

int Queen::QueenArrange()
{
	queue<Node> q;
	Node f(n);
	q.push(f);
	while (!q.empty())
	{
		Node x = q.front();
		q.pop();
		if (x.t == n)
		{
			++ansNum;
		}
		//一次性將當前節點的所有擴充套件節點考慮完,符合條件的插入佇列
		for (int i = 1; i <= n; ++i)
		{
				//利用剪枝函式,將不符合條件的分支切掉
				if (x.check(i))
				{
					Node child(x);
					++child.t; 
					child.pos[child.t] = i; //記錄位置
					q.push(child);
				}
		}
	}
	return ansNum;
}

int main()
{
	int n = 8;
	Queen queen(8);
	cout << queen.QueenArrange() << endl;
}