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;
}

 

猜你喜欢

转载自blog.csdn.net/qq_29869043/article/details/82958873