八皇后问题

流过昼夜 提交于 2020-03-26 02:23:55

八皇后问题

8 x 8的棋盘上保证每一行、每一列和两个斜列上只有一个皇后。

递归分析

程序结构:

  • 初始化
  • 循环八次:
    • 放置一个皇后
    • 若满足防止条件则放置皇后
    • 若不满足则回退,增加一步再放置
  • 直到放置到最后一个皇后

自相似的关系提取

  • 过程:
    • 找到N个皇后的适合位置
  • 划分:
    • 找到第N-1个皇后合适的位置
    • 找到第N个皇后的位置
  • 递归终止条件
    • 找到最后一个皇后的位置

算法流程

  • Step1:
    • 数据初始化
  • Step2:
    • 从col列开始摆放第n个皇后,挨个测试列是否可行,需要先测试当前位置是否安全:
      • 若安全,摆放第n个皇后,并且宣布占领(横竖撇捺都要占领)
      • 若未测试完所有的的行
        • 递归测试下一行
        • n = N-1 时打印结果
      • 如果当n >= N-1时说明无法摆放或摆放完毕时需要回溯
  • Step3:
    • 输出结果

数据结构

  • place:int数组【0....7】
    • 第n行皇后所占位置的列号
    • 主要用于输出结果
  • flag:bool数组【0....7】
    • 表示col列上能放置皇后
  • d1:bool数组【0....14】
    • (n,col)所在上对角线上是否可以放置皇后 (n-col+7)(保证为正)
  • d2:bool数组【0....14】
    • (n,col)所在下对角线上是否可以放置皇后(n+col)

程序思路

  • 是否能放置

    • flag[col] and d1[n-col+1] and d2[n+col]
  • 放置皇后

    • place[n] := col;{摆放皇后}
    • flag[col] := false; {宣布占领}
    • d1[n-col+7] := false; {占领上对角线}
    • d2[n+col] := false; {占领下对角线}
  • 删除皇后(回溯:探求所有可能):

    • flag[col] := true;
    • d1[n-col+1] := true;
    • d2[n+col] := true;

代码

/*
八皇后问题
*/
#include <stdio.h>
#include <iostream>
using namespace std;
//初始化
int place[8] = {0};
bool flag[8] = {1,1,1,1,1,1,1,1};
bool d1[15] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
bool d2[15] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int number = 0;
void print(){
	int col,i,j;
	number++;
	cout<<"No."<<number<<endl;
	int table[8][8] = {0};
	for(col = 0;col < 8;col++){
		table[col][place[col]] = 1;
	}
	for(i = 0;i < 8;i++){
		for(j = 0;j < 8;j++){
			cout<<table[i][j]<<" ";
		}
		cout<<endl;
	}
}
void generate(int n){
	int col;
	for(col = 0;col < 8;col++){
		if(flag[col] && d1[n-col+7] && d2[n+col]){
			place[n] = col;
			flag[col] = 0;
			d1[n-col+7] = 0;
			d2[n+col] = 0;
			if(n < 7){
				generate(n+1);
			}
			else{
				print();
			}
			//回溯
			flag[col] = 1;
			d1[n-col+7] = 1;
			d2[n+col] = 1;
		}
	}
}

int main(int argc, char const *argv[])
{
	generate(0);
	return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!