前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >八皇后问题(回溯)

八皇后问题(回溯)

作者头像
Ch_Zaqdt
发布2019-01-10 14:37:34
发布2019-01-10 14:37:34
51400
代码可运行
举报
文章被收录于专栏:Zaqdt_ACMZaqdt_ACM
运行总次数:0
代码可运行

在做这道题之前搜了一下回溯和递归的区别,递归就是一个劲的往下搜,搜到头了走不通了,再倒回来换条路继续搜,而回溯就是搜到结果以后再回头重新换个点继续重新搜。

       这道题是紫书上P191的一道例题,也是一道经典的回溯搜索题,题的描述就是有一个8*8的棋盘,然后有8枚棋子,问一行或者一排或者对角线上只能放一枚棋子,能有多少种放法。

       思路就是按列去搜索,对于选定的列,然后再依次对行进行遍历,判断这个点是否满足条件,满足的话就选定该点进行下一列的搜索。对于判断是否满足条件的话,这里我用pre[x]=y,表示y行x列,所以当|pre[x] - pre[y]| == |x - y|的时候,肯定是在一条对角线上的。判断是否在同一行或者同一列就很好判断了,剩下的就看代码吧。

代码语言:javascript
代码运行次数:0
复制
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 10;
int pre[MAXN];
int Queen_Num = 8;
int num = 0;

void Output(int pre[]){
	for(int i = 0; i < Queen_Num; i++){
		printf("(%d, %d)\t",pre[i] + 1, i + 1);        // 输出坐标
	}
	printf("\n");
	num++;            // 方案数++
}

bool check(int pre[], int col){
      for(int i = 0; i < col; i++){           // 因为时从第一列开始放,所以只需判断之前的列的行是否重复
	  if(pre[i] == pre[col] || abs(pre[i] - pre[col]) == col - i){  // 当在同一对角线上时,无论主副都有|pre[i]-pre[col]|==|i-col|
		return false;
	 }
     }
     return true;
}

void dfs(int pre[], int col){
	if(col == Queen_Num){            // 当列数达到8时调用输出函数
		Output(pre);
		return ;
	}
	for(int i = 0; i < Queen_Num; i++){    // col为列,遍历行
		pre[col] = i;                  // 将第i行col列存入数组
		if(check(pre,col)){            // 判断这样放是否可行
			dfs(pre,col+1);              // 进行下一列
		}
	}
}

int main()
{
	memset(pre,0,sizeof(pre));
	dfs(pre,0);                    // 从第0列开始
	printf("总方案数:%d\n",num);
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年03月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

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