zoukankan      html  css  js  c++  java
  • 八皇后问题解题报告(dfs

    这里是代码传送门

    所谓八皇后问题,一开始接触,上学期舍友提及的,但是因为各种原因,水平不够,并没有关心,偶然之间,再次遇见,便进行的尝试(棋盘是0-7的,不是1-8的...开始打弄错了)

    所谓八皇后问题,就是在8X8的棋盘上,求如何让可以往八个方向直走的皇后不互相攻击的摆放方法的解;
    很显然,我的第一想法是用深搜剪枝(书上说是 回朔法 )
    如何实现呢?我的想法是,先预定让每个皇后占一行,然后暴力搜索皇后所在列的情况,然后递归剪掉不满足的情况;

    代码如下

    
    #include<cstdio>
    #include<queue>
    #include<stack>
    #include<string>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<iomanip>
    #include<algorithm>
    #include<iostream>
    #define PI acos(-1)
    #define ull unsigned __int64
    #define Min(a,b) ((a>b)?b:a)
    #define Max(a,b) ((a>b)?a:b)
    #define INF 1000000007
    using namespace std;
    bool v[8]={0};//用来记忆
    int node[8];//记录不同行的皇后所在的列
    int coun=0;//统计一共解法
    void dfs(int t)
    {	
     	if(t==8)//如果能达到8行,说明是满足条件的,不然会被剪枝
     	{
     		for(int i=0;i<8;i++) printf("(%d,%d) ",i,node[i]);
     		printf("
    ");
     		coun++;
     		return ;
    	 }
    	for(int i=0;i<8;i++)//遍历
    	{
    		if(!v[i])//皇后的列数不能相同
    		{
    			int flag=true;//判断斜线
    			for(int j=0;j<t;j++)
    			{
    				if(node[j]==i-(t-j)||node[j]==i+(t-j))
                    //遍历前面已经给出的皇后是否在同一斜线位置,前面一个是k=-1的斜线,后面是k=1的斜线
    				{
    					flag=false;//如果在同一斜线,则不能满足条件
    					break;
    				}
    			 } 
    			 if(flag)//满足条件
    			 {
    			 	node[t]=i;
    				v[i]=1;
    				dfs(t+1);
    				v[i]=0;//这一步很重要
    			 }
    			
    		}
    		
    	}
    	return ;
     }
     int main()
     {
     	dfs(0);
     	printf("count=%d
    ",coun);
      } 
    

    最终结果给出了92种情况,与网上无差。
    之后参考了《挑战程序设计》p193页,发现思想与第一种方法无差
    但是,他给出了另外一种更高效的解法。
    定义的bool类型为二维的 bool vis[3][18],可以更加高效的实现算法:

    改进版代码如下:

    #include<cstdio>
    #include<queue>
    #include<stack>
    #include<string>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<iomanip>
    #include<algorithm>
    #include<iostream>
    #define PI acos(-1)
    #define ull unsigned __int64
    #define Min(a,b) ((a>b)?b:a)
    #define Max(a,b) ((a>b)?a:b)
    #define INF 1000000007
    using namespace std;
    bool vis[3][18]={0}; 
    int node[8];
    int coun=0;
    void dfs(int t)
    {	
     	if(t==8)
     	{
     		printf("(%d,%d)",0,node[0]);
     		for(int i=1;i<8;i++) printf("	(%d,%d)",i,node[i]);
     		printf("
    ");
     		coun++;
     		return ;
    	 }
    	for(int i=0;i<8;i++)
    	{
    		if(!vis[0][i]&&!vis[1][i+t]&&!vis[2][t-i+8])
    //V[0][i]表示记忆,vis[1][i]表示左下右上的斜线,vis[2][i]表现左上右下 
    		{
    		 		vis[0][i]=vis[1][i+t]=vis[2][t-i+8]=1;													 
    			 	node[t]=i;
    				dfs(t+1);
    				vis[0][i]=vis[1][i+t]=vis[2][t-i+8]=0;
    			
    		}
    		
    	}
    	return ;
     }
     int main()
     {
     	dfs(0);
     	printf("count=%d
    ",coun);
      } 
    
    

    只用了一层循环,这告诉了我们一点:

    学好数学是很重要的

  • 相关阅读:
    Method of Four Russians 学习笔记
    一道不知道哪里来的数论题
    ICPC2021银川 游记
    决策单调性优化dp学习笔记
    浅谈如何优美地实现线段树?
    2021 EC Final 2020 题解
    5.5 SYSU校内训练
    5.4 SYSU校内训练
    存储相关招聘信息-长期
    screen几个使用方法
  • 原文地址:https://www.cnblogs.com/Anani-leaf/p/5219820.html
Copyright © 2011-2022 走看看