《算法笔记》codeup 100000583 问题 D: 八皇后 (N皇后代码解析)

思路:

从棋盘的第一列开始,尝试在当前列的每一行摆放皇后。如果当前在行列上摆放暂时不会引起冲突,则保存摆放的位置。然后进入下一行重复上述操作,直到每一列都完成操作。

解答:

#include <cstdio>
#include <iostream>
#include <cmath> 
#include <algorithm>
using namespace std;

/*
    从棋盘的第一列开始,尝试在当前列的每一行摆放皇后。
    如果当前在行列上摆放暂时不会引起冲突,则保存摆放的位置。
    然后进入下一行重复上述操作,直到每一列都完成操作。
*/

int plan_num = 0;                  // 方案数量
int row_of_colm[11];               // 0元素弃置,第i个元素表示第i列上的皇后所在行的序号
bool if_occupied[11] = {false};    // 0元素弃置,第1到10个元素分别表示第1到10行时候已经放了皇后
int plan[92];                      // 数组的每个元素表示一种方案

void NQueneP(int colm, int n) {    // colmumn表示列号
    if(colm == n + 1) {	           // 递归边界
		plan_num++;
		for(int i = 1; i <= n; i++) {  // 摆放方案保存为一个整数
            plan[plan_num] += row_of_colm[i] * pow(10, i - 1);
        }
		return;                    //返回上一层递归出口 
	} 

	//从第一行开始枚举试图摆放皇后 
	for(int row = 1; row <= n; row++) {
		if(if_occupied[row] == false) {    //当前行未被占用 
			bool flag = true;              //试图在colm列row行摆放皇后
            
			for(int pre = 1; pre < colm; pre++) {  // 此时第1列到第colm-1列已处理完,这些列上的皇后已摆好,第i列上的皇后所在行号保存在row_of_colm[i]中,遍历前面的列检查是否会与当前行列上的皇后有对角冲突
				if(abs(colm - pre) == abs(row - row_of_colm[pre])) {  // 如果前面某皇后的行列与当前行列的差的绝对值相当,则对角冲突
					flag = false;          //不能在当前行列摆放 
					break;  
				}
			}

			//若为false,则不能在当前行列摆放,基于进入本次递归前确定的摆放位置加上本次探查的位置组成的摆放方案已经不可能成功,无需进一步摆放下去,直接进入下一行
			if(flag == true) {
				row_of_colm[colm] = row;            //在colm列row行摆放皇后 
				if_occupied[row] = true;            //标记row行已被占用 
				NQueneP(colm+1, n);                 //进行下一列处理 

                // 到达此处表明基于该行列的情况已经探查完,循环准备进入下一行
				if_occupied[row] = false;           // 清除占用标记 
			}
		}
	} 
}
int main(){
	int n = 8;       // 皇后数
	NQueneP(1, n);   //从第一列开始摆皇后 
    sort(plan + 1, plan + (plan_num + 1));

    int test_num;
    while(scanf("%d", &test_num) != EOF) {
        for(int i = 1; i <= test_num; i++) {
            int index;
            scanf("%d", &index);
            printf("%d\n", plan[index]);
        }
    }
    /*
	cout << "共有" << plan_num << "种摆法" << endl;
    for(int i = 0; i <= 92; i++) {
        printf("%d  %d\n", i, plan[i]);
    }
    */
	return 0;
} 

笔记:

  1. 代码是比照《算法笔记》中对应部分写的,原书中的代码的变量名让人有点难以理解代码的逻辑,实际上就是遍历每一列,在每一列上遍历每一行。
  2. 我个人认为书中提到这段代码的回溯思想,应该是体现在某个位置上发现会与之前摆好的皇后起冲突后,就跳过进一步的摆法,直接探查当前列下一行。但这好像与书中说的“五皇后时摆好351后可以发现剩下两个位置一定会冲突”不太一样,实际上我都不太明白它是怎样发现一定会冲突。
  3. codeup编译错误可以点击查看提示。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值