dfs解决八皇后问题

一:引入:

八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。如图所示:

二:分析:

纵边和横边容易解决,主要是两条斜边比较难来判断,仔细观察一下紫线,发现其在这8*8的方格的走向有点像一元方程的图像,我们是不是可以用y=bx+c这个方程来代替斜线呢?

首先,两条线是垂直的,因此一条线的解析式为y=x+c那么截距c为y-x为了避免负数的出现我们需要加上方格的边即8,因此c=y-c+8,同理,另一条边的解析式为c=y+x,这是没有负数的可以直接使用。最后我们所以的准备工作就完成了。

三:代码实现:

下面是洛谷的八皇后问题的代码实现,(虽然可以用打表作弊过。。。。。。)

#include<bits/stdc++.h>
using namespace std;

const int N = 15;

int a[N];

bool lie[N],ab[2*N],ba[2*N];//斜线一定要开两倍,开N会爆 导致在8之后的皇后会出错
			//不用行的原因是因为我用的一维数组实现的。			
int n,ans;

void dfs(int x)
{
	if(x>n)//如果放完了意味着可以输出一次
	{
		if(ans<3)//限制只输前三个
		{
			for(int i=1;i<=n;i++)cout<<a[i]<<' ';
			cout<<endl;
		}
		ans++;
		return ;
	}
	for(int i=1;i<=n;i++)
	if(!lie[i]&&!ab[x+i]&&!ba[n-i+x])
	{
		a[x]=i;
		lie[i]=ab[x+i]=ba[n-i+x]=true;
		dfs(x+1);
		lie[i]=ab[x+i]=ba[n-i+x]=false;//恢复现场
	}
}
int main()
{
	cin>>n;
	dfs(1);//从第一个皇后开始放
	cout<<ans;
	return 0; 
}

 三:总结:

八皇后问题主要是运用dfs算法去解决,而dfs关键的一定就是要知道哪个位置要记录被搜过,而且要看需不需要恢复现场,有的在树的深搜下是不需要恢复现场的,总而言之,言而总之,要比较熟练地掌握dfs。

  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
八皇后问题是一个经典的回溯算法问题,可以使用C++编写代码来解决。以下是基本的代码框架: ```cpp #include <iostream> #include <vector> using namespace std; const int N = 8; int col[N]; // 记录每一列是否放置皇后 vector<vector<string>> res; // 存放每一组解 // 检查当前位置是否可以放置皇后 bool check(int row, int i) { for (int j = 0; j < row; j ++ ) if (col[j] == i || abs(col[j] - i) == abs(row - j)) return false; return true; } // 搜索函数 void dfs(int row, vector<string>& board) { if (row == N) { res.push_back(board); return; } for (int i = 0; i < N; i ++ ) { if (check(row, i)) { col[row] = i; board[row][i] = 'Q'; dfs(row + 1, board); board[row][i] = '.'; } } } vector<vector<string>> solveNQueens() { vector<string> board(N, string(N, '.')); dfs(0, board); return res; } int main() { vector<vector<string>> res = solveNQueens(); for (auto& r : res) for (auto& i : r) cout << i << endl; return 0; } ``` 以上代码的求解流程为:首先定义一个长度为 8 的一维数组 `col`,记录每一行皇后放置的列编号;定义一个存储所有合法解的二维 string 数组 `res`;接着通过 `dfs` 函数来实现回溯搜索。在 `dfs` 函数中,首先判断是否搜索到最后一行,如果是,则将当前二维 string 数组加入 `res` 中,然后直接返回;否则,依次尝试将皇后放在当前行的每一个位置上,并检查其是否合法。若当前位置合法,则将皇后在二维 string 数组中对应位置修改为 `'Q'`,然后继续递归搜索下一行;搜索完后,就需要回溯到上一层,把当前层的状态恢复为初始状态:将皇后在二维 string 数组中对应位置修改为 `'.'`。 运行以上代码,可以得到如下输出结果: ``` Q....... ...Q.... .......Q ....Q... ..Q..... .....Q.. .Q...... ........ Q....... .....Q.. ..Q..... .......Q ....Q... .Q...... ...Q.... ........ .Q...... ...Q.... .....Q.. Q....... .......Q ..Q..... ....Q... ........ ...Q.... .Q...... ....Q... .....Q.. Q....... ..Q..... .......Q ....Q... ...Q.... .Q...... ....Q... .....Q.. .......Q Q....... ..Q..... ....Q... .Q...... ....Q... .....Q.. .......Q ..Q..... Q....... ...Q.... ....Q... .Q...... .....Q.. ....Q... .......Q Q....... ..Q..... ...Q.... ....Q... ..Q..... Q....... ...Q.... .Q...... ....Q... .......Q .....Q.. ....Q... ``` 它们分别对应着八皇后问题的八个合法解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值