N皇后问题经典DFS

这篇博客探讨了HDU 2553“N皇后问题”的解决方法,主要使用DFS进行求解。博主强调了剪枝在DFS中的重要性以避免超时,并提供了算法分析,包括不同方向的判断条件。同时,提到了当N大于11时,可能需要使用位运算或数据结构舞蹈链来处理更大的问题规模,超过一定规模则成为NP问题。博客还包含AC代码和细节处理,如提前计算小规模问题的答案以优化运行时间。
摘要由CSDN通过智能技术生成

题目 HDU 2553“N皇后问题”

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2553


前言:

通过这个题学习到了剪枝。暴力破解会超时啊,就很拿人。DFS的难点在于扩展子节点的时候如何构造停止递归并返回的条件,就要用到剪枝函数。

依然举个例子,分析一下4皇后怎么搞。

思路如下:

从第一行开始放皇后:第一行从左到右有4种方案,产生4个结点;第2行,排除同列和斜线,拓展新的结点,注意不用排除同行,因为第二行和第一行已经是不同行的了。继续拓展第三行和第四行,结束。

下面上分析图:

这下应该很明白了吧!

这个题其实用BFS和DFS都可以写,但是DFS毕竟比BFS代码量更少。

算法分析:

设左上角是原点(0,0),已经放好的皇后的坐标是(i,j),不同行不同列不同斜线的新皇后的坐标是(r,c)那么:

1、横向,不同行:i≠r

2、纵向,不同列:j≠c

3、斜对角:从(i,j)向斜对角方向走a步,那么新坐标(r,c)有4种情况,即左上(i-a,j-a)右上(i+a,j-a)左下(i-a,j+a)右下(i+a,j+a)综合起来就是|i-r|=|j-c|新皇后的位置不能放在斜线上,需要满足|i-r|≠|j-c|

这个题注意是N<=10,如果N>11需要用位运算/数据结构舞蹈链,这也仅仅是到N=15,如果N再大就是NP问题了

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,tot = 0;
int col[12] = {0};
bool check(int c,int r){//检查是否和已经放好的皇后冲突 
	for(int i;i<r;i++)
			if(col[i] == c||(abs(col[i]-c) == abs(i-r)))//取绝对值
				return false;
			return true; 
}
void dfs(int r){//一行一行放皇后 
	if(r == n){//所有皇后都放好了,递归返回 
		 tot++;
		 return;
	}
	for(int c = 0;c<n;c++)//在每一列放皇后
		if(check(c,r)){//检查是都合法 
			col[r] = c;//在第r行的第c列放皇后 
			dfs(r+1);//继续放下一行皇后 
		} 
}
int main(){
	int ans[12] = {0};
	for(n = 0;n<=10;n++){//算出所有N皇后的答案,注意先打表,不然会超时
		  memset(col,0,sizeof(col));//清空,准备计算下一个N皇后问题
		  tot = 0;
		  dfs(0);
		  ans[n] = tot;//打表 
	}
	while(cin>>n){
		if(n == 0)
			 return 0;
	    cout<<ans[n]<<endl;
	}
	return 0;
}

细节处理:

1、打表。在main()中提前算出了从1到10的所有N皇后的问题的答案,并存储在数组中,等读取输入后立刻输出。如果不打表,会超时的!

2、回溯判断check()仅仅需要判断纵向和对角线方向,因为在递归是已经是按照不同的行放置的。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值