zoukankan      html  css  js  c++  java
  • 回溯算法与八皇后问题

        回溯法:在递归构造中,生成和检查的过程可以有机结合起来,从而减少不必要的枚举。把问题分解为若干个步骤求解时,如果当前步骤没有合法选择,则函数将返回上一级的递归调用,该现象称为回溯法。所以递归枚举通常被称为回溯。

        8皇后问题:在8*8的棋盘上放置了8个皇后,使得他们互不攻击,每个皇后的攻击范围为同行,同列和同对角线。要求找出共有多少种放法。

     分析:最简单的思路是枚举“64个格子的子集”,使得子集中恰有8个格子满足条件。但是枚举64个格子有2^64,显然是个糟糕的模型。第二种思路是“从64个格子中选8个,然后判断是否满足条件“,根据组合数可知这个方案达到10^9数量级,比第一种方案好,但是也不够好。下面用回溯法来解决。用c[x]表示第x行

    的皇后的列号,于是问题转变为了8!=40320生成全排列问题。下面给出了回溯法解决8皇后问题的代码:

    int c[maxn];
    int ans;
    void dfs(int curr,int n){   //n皇后问题
    	if (curr ==n){ ans++;return; }
    	int i, j;
    	for (i = 0; i <n; i++){
    		c[curr] = i;  //尝试吧curr行的皇后放在第i列
    		for (j = 0; j< curr; j++){
    			//检查是否与已经放置的皇后冲突
    			if (c[curr]== c[j] || c[curr] - curr == c[j] - j || c[curr] + curr == c[j] + j)break;
    		}
    		//j==i说明上述循环没有提前终止,放在i列是合理的
    		if (j == curr) dfs(curr + 1,n);
    	}
    }

     可以继续提高程序效率。用vis[3][]来标记当前皇后所在的列和对角线是否有其他皇后的攻击,测试了一下,时间大约比上面代码快3倍多int vis[3][maxn];

    int vis[3][maxn];
    void dfs(int curr,int n){
    	if (curr == n){ ans++; return; }
    	for (int i = 0; i < n; i++){
    		if (!vis[0][i] && !vis[1][curr + i] && !vis[2][curr - i + n]){
    			vis[0][i] = vis[1][curr + i] = vis[2][curr - i + n] = 1;  //标记为放
    			c[curr] = i;      //无需打印的话可以不使用数组c
    			dfs(curr + 1, n);
    			vis[0][i] = vis[1][curr + i] = vis[2][curr - i + n] = 0;  //撤销标记
    		}
    	}
    }
    

      

  • 相关阅读:
    HashMap源码分析
    Vector和Stack源码分析/List集合的总结
    LinkedList源码分析
    ArrayList源码分析
    第三章 数据链路层(三)
    Java常考面试题(五)
    hibernate(一) 第一个hibernate工程
    回想过去,展望未来
    “Cannot load php5apache2_4.dll into server”问题的解决方法
    win7下80端口被(Pid=4)占用的解决方法
  • 原文地址:https://www.cnblogs.com/td15980891505/p/5821030.html
Copyright © 2011-2022 走看看