前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >暴力搜索------回溯法

暴力搜索------回溯法

作者头像
刘开心_1266679
发布2019-02-14 15:32:09
8560
发布2019-02-14 15:32:09
举报

回溯法(backtracking)是深度优先搜索(DFS)的一种,按照深度优先的顺序便利解答树。应用范围很广,只要能把待求解的问题分成不太多的步骤,每个步骤又只有不太多的选择,都可以考虑应用回溯法。在学习回溯法之前,一定要保证递归程序能熟练准确地写出。

       当把问题分成若干步骤并递归求解时,如果当前步骤没有合法选择则函数将返回上一级递归调用。

例如:

       八皇后问题:在棋盘上放置八个皇后,使得它们互不攻击,每个皇后的攻击范围是同行同列同对角线,找出所有解的个数。

       如果把问题相成从64个格子中选8个格子,那么根据组合数学需要4.426*10^9种方案,但是如果用数组C[x]表示第x行皇后的列编号,则问题变成了全排列生成问题。而0~7的全排列一共有8!=40320个,枚举量不会超过它 。

       下面以四皇后问题阐述具体思路:

第一行,皇后可以在第一列、第二列、第三列、第四列。用a[i][j]来表示皇后可能放置的位置,如图

假设第一行的皇后在a[0][0],那么在第二行皇后可能放置的合法位置如图

假设第二行皇后放在a[1][2],那么第三行无法放皇后,所以回溯到第一行的a[0][0],走下一条路a[1][3],如图

第四行无法再放置皇后,说明第一个皇后不能在a[0][0],回溯到最开始,让皇后放置在a[0][1],依此类推得到解答树。

       观察解答树,改变一次行,遍历四个列(a[1][0]和a[1][1]的情况由于不放置皇后所以没有画在图上,但是这两种情况的否定需要遍历判断),所以只需要用一个一维数组C[x]来表示第x行皇后的列编号即可。代码如下:

需要在主函数中读入n(n*n的棋盘),并将解的个数tot清零,然后调用Dfs(0),即可求得解。

代码语言:javascript
复制
void Dfs(int cur)                                //cur表示行 
{
	if(cur == n)                             //递归边界,每走到此得到一个解
		tot++;                           //tot表示解的个数 
	else
	{
		for(int i = 0; i < n; i++)       //i表示列 
		{
			int ok = 1;                  //判断能否放皇后的标志 
			C[cur] = i;                  //尝试把第cur行的皇后放在第i列 
			for(int j = 0; j < cur; j++) //j表示行,通过检查前面几行判断能否放皇后 
			{
		                /*判断列、主对角线、副对角线与前几行皇后是否冲突*/ 
				if(C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j])
				{
					ok = 0;
					break;
				} 
			} 
			if(ok)
				Dfs(cur + 1);
		}
	}
} 

C[cur] == C[j] 、cur - C[cur] == j - C[j]、cur + C[cur] == j + C[j]的理解如下:

由于是逐行放置,所以横向一定不会冲突,只需检查是否纵向和斜向冲突即可,在直角坐标系中,y = -x与y = x为正斜向线,类比坐标系,cur为行,抽象为横坐标,C[cur]为列,抽象为纵坐标,由于不一定要通过原点,所以y-x与y+x可以为任意常数,只要这个常数与前一行相等,说明两皇后斜向冲突。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年03月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档