八皇后

八皇后也是个经典算法题目了。 早有耳闻,不曾亲见。

在国际象棋中,皇后可以在棋盘上攻击横竖斜八个方向上的敌人(这也太diao了叭),所以就想想出一种算法,能让这八个皇后同时安置在棋盘上,皇后之间不能有冲突。挺有意思的(呵,实际上就是宫斗好吧。。。)

题目来自洛谷试炼场深度优先搜索——八皇后https://www.luogu.org/problemnew/show/P1219

题目描述

这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

输入格式:

一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。

输出格式:

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。


输入样例: 
6
输出样例: 
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

刚拿到这道题目,我大脑中的暴力因子就异常活跃——用一个二维数组来存下整个棋盘的状态,然后开始逐行深度优先搜索

这道题我是用到了搜索与回溯,这里先上一个超暴力下的超时算法(\流汗)。

超时算法
int sum=0;
int map[100][100], ans[100];
//位置检查 
bool CheckPos(int x, int y, int n){
    for(int i=1; i<=n; i++){
        if(map[i][y]==1)
                return false;
        for(int j=1; j<=n; j++)
            if(abs(i-x)==abs(j-y) && map[i][j]==1)
                return false;
    }
    return true;
}
void Queen(int row, int n){
    if(row>n){
    	
        sum++;
        if(sum<=3){
        	
            for(int i=1; i<=n; i++)
                   cout<<ans[i]<<" ";
            cout<<endl;
        }
        return ;	
    }

    for(int col=1; col<=n; col++){	
		
        if(CheckPos(row, col, n)){
        	
            map[row][col]=1;	//放入皇后 
            ans[row]=col;
            Queen(row+1, n);	//搜索下一列 
            
            map[row][col]=0;	//复原回溯 
        }
    }
}

上面这种算法的结果在预料之中,最后两个样例2/8,87分TLE掉了,毕竟这个做法暴力上又加暴力结果肯定是超时,太暴力了!

开始探索其他的有效算法吧,仔细想想,我非要把整个棋盘全存下来吗?只要用一个一维数组存下每一行皇后所在的列号,同时用辅助数组标识出该皇后所占领的列号和对角线不就行了。

算法思路清晰,其实和上面那个超时算法大致相同,都是搜索与回溯,话不多说这就开始实现。

升级版!

//DFS八皇后 
#include<iostream>
#include<cstdio> 
#include<cstring>
using namespace std;
int sum=0;
//依次是行 —列 —双对角线 
int a[100], b[100], c[100], d[100];
//dfs与回溯 
void Queen(int i, int n){
	
    if(i>n){
        sum++;
        if(sum<=3){		//前三行 
            for(int k=1; k<=n; k++)
                cout<<a[k]<<" ";
            cout<<endl;
        }
        return;	
    }
    else{
	    for(int j=1; j<=n; j++){		
	        if(!b[j] && !c[i+j] && !d[i-j+n]){	//其他皇后没有占领
	        
	            a[i]=j;		//i行j列安置皇后 
	            b[j]=1;		//纵列占领 
	            c[i+j]=1; d[i-j+n]=1;	//对角线占领 
	            
	            Queen(i+1, n);	//dfs
	            
	            b[j]=0;
	            c[i+j]=0;
	            d[i-j+n]=0;
	            //复原回溯 
	        }
	    }//for
	} 
}
int main()
{
	int n;
    cin>>n;
    Queen(1, n);
    cout<<sum; 
    return 0;
}

到此结束问题解决,原来这就是有名的八皇后啊(呵, 宫斗)。

我对深搜的粗略理解

就是沿着可行路径逐步向下搜索,如果有一天发现走到了一个无路可去的死胡同,就跳出当前操作回到了上一步,探索其他可行路径。就是这样一点一点的探索,直到到达了终点或者搜索了所有可行路径,才结束搜索操作

去吧,但愿你一路平安,桥都坚固,隧道也光明!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值