不使用递归,一次性解决八皇后问题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

 思路:一般来说,八皇后问题使用递归或者递推的方法,一:在棋盘某位置放一个皇后;二:判断皇后是否与前面已有皇后形成相互攻击;三:如果没有相互攻击,则调用递归函数,继续放置下一列皇后;四:放置完8个不形成攻击的皇后,变得到一个解。

如果我们设置一个数组arr[8],每个元素的值代表棋牌中该行所放置皇后的位置,例如arr[1]=2,说明第二行(下标从0开始)放置位置为第三列(下标同样从0开始)。自然可以枚举出所有排列顺序,进行判断,但是如何枚举所有顺序呢?这里用到了C++中next_permutation函数。我们用string s=“01234567”代表第一次的位置进行判断,如果不合适,使用next_permutation排序成01234576进行循环,依次类推,知道所有可能排序枚举完为止。

 

#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <string>

using namespace std;

int ans = 0;

int _tmain(int argc, _TCHAR* argv[])
{
	string s = "01234567";
	int arr[8];
	int flag = 1;			//当前位置是否可以存放皇后的标志
	do{
		flag = 1;
		for (int i = 0; i < 8; i++)
		{
			arr[i] = s[i] - '0';	//将char类型转换成int类型,存放到arr数组中
			for (int j = 0; j < i; j++)
			{
				if (abs(i - j) == abs(arr[i] - arr[j]))	//如果在同一列或者对角上,flag=0,不合适
				{
					flag = 0;	
					break;		//如果不合适,后面的行无需放置,跳出本次循环,结束后面行的比较
				}
			}
			if (flag == 0)		//如果是不合适跳出来的,说明这个顺序不合适,跳出进行next_permutation
				break;
			if (i == 7 && flag == 1) //如果flag=1而且i=7,说明进行到最后一行并且本次顺序合适,结果加1
			{
				ans++;
			}
		}
	} while (next_permutation(s.begin(), s.end()));		//获得下一个顺序
	cout << ans << endl;
	return 0;
}

 

    原文作者:八皇后问题
    原文地址: https://blog.csdn.net/weixin_41857869/article/details/88325015
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞