对于DFS和BFS的一些思考【I】 洛谷P1443以及洛谷P1219八皇后问题

        对于DFS在刚接触时因一句不撞南墙不回头就理解的透彻了许多,DFS也许更像是一种特殊的暴力方法,可以理解为对每条可行的路都尝试一遍:如左图的标记:从节点1开始,先1→2→3,在节点三没路走了便回退到节点2,在节点2也没可行的路走于是回退到节点1,又从1→4→5→6,到6无路可走一步步回退到4,即又从4→7→8....以此往复。所以DFS可以用栈来表现这一回退和搜索的过程(进栈弹栈操作),也可以用递归操作来实现,于是我这只蒟蒻就用递归的写法写了一些板子题供大家参考。

第一道经典八皇后问题:在一个N*N的棋盘上放置N个皇后,每个皇后的攻击范围为与其在同一列同一行和对角线上如图:

即为这样的米字型攻击区域,那么剩下的绿色的格子才能放置第二个皇后,现在给出一个棋盘大小N,求N个皇后放置的方案数;

经典的搜索板子题,可以发现对应每行和对应每列只能放置一个皇后,而对角线的攻击范围,我们可以发现有一条对角线的特征为(x-y)为定值,另一条对角线的特征为x+y为定值。因此我们分别用四个数组的状态来模拟该攻击区域是否能放置皇后,代码如下:

#include<bits/stdc++.h>

#define int long long 
using namespace std;
const int N=1e7+5;
int a[1000][1000],x_[5]={1,-1,0,0},y_[5]={0,0,1,-1},cnt=0,n;//x_、y_数组一起并用模拟上下左右的方向 
bool y[1000],yx[1000],xy[1000];// y数组模拟列 yx模拟y-x的对角线 xy模拟y+x的对角线
void dfs(int x){ 
    if(x==n+1){
        cnt++;
        return ;
    }
    for(int i=1;i<=n;i++){//即对于从[x][1]→[x][n]寻找每个可行的位置
        if(!y[i]&&!yx[x-i+200]&&!xy[x+i]){
            y[i]=1;
            yx[x-i+200]=1;
            xy[x+i]=1;//标记该位置已被选中
            dfs(x+1);//进行下一行的搜索
            y[i]=0;
            yx[x-i+200]=0;
            xy[x+i]=0;//恢复上一行的标记
        }
    }
    return ;//return就是当1->n没有位置可以选的时候返回上一行重新选择 
}
signed main(){
    cin>>n;
    dfs(1);
    cout<<cnt<<endl;
}

于是简单的N皇后问题我们递归方法DFS就解决了,洛谷上P1219八皇后问题就不止是问放置的方案数,还有前三种放置的方法,因此对于前三种输出还要处理,话不多说直接上代码注释:

#include<bits/stdc++.h>

#define int long long 
using namespace std;
const int N=1e7+5;
int a[1000][1000],x_[5]={1,-1,0,0},y_[5]={0,0,1,-1},cnt=0,n;//x_、y_数组一起并用模拟上下左右的方向 
bool y[1000],yx[1000],xy[1000];// y数组模拟列 yx模拟y-x的对角线 xy模拟y+x的对角线
void dfs(int x){//由于还要查询前三种放置方法,因此模拟一个棋盘a[][]; 
    if(x==n+1){
        cnt++;
        if(cnt>3){
        	return;
		}
		else{
			for(int i=1;i<=n;i++){ 
				for(int j=1;j<=n;j++){
					if(a[i][j]==1){
						cout<<j<<" ";
					}
				}
			}
			cout<<endl;
			return ;
		}
    }
    for(int i=1;i<=n;i++){//即对于从[x][1]→[x][n]寻找每个可行的位置
        if(!y[i]&&!yx[x-i+200]&&!xy[x+i]){
            y[i]=1;
            a[x][i]=1;//同理 如果该点能放置皇后就记录a[x][i]=1;并在深搜后回溯 
            yx[x-i+200]=1;
            xy[x+i]=1;//标记该位置已被选中
            dfs(x+1);//进行下一行的搜索
            y[i]=0;
            yx[x-i+200]=0;
            a[x][i]=0;
            xy[x+i]=0;//恢复上一行的标记
        }
    }
    return ;//return就是当1->n都没有放置方法就回溯到上一层 
}
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=n;j++){
    		a[i][j]=0;
		}
	}
    dfs(1);
    cout<<cnt<<endl;
}

至于BFS的写法本蒟蒻还没写出来(太菜了别骂了),明天会更新P1443马的遍历以及补充一些DFS模板题供各位大佬食用。

    传送门:

八皇后问题:[USACO1.5]八皇后 Checker Challenge - 洛谷

马的遍历:马的遍历 - 洛谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值