八皇后问题回溯算法

#include<iostream>
#include<vector>
using namespace std;
int dir_x[8] = { -1, -1, -1, 1, 1, 1, 0, 0 };//创建两个方向数组
int dir_y[8] = {  0 , 1, -1, 0, 1,-1, 1,-1 };
              //  L  LU  LD  R RU RD  U  D      L左,R右,D下,U上 
void copy_attack(int(*attack)[8], int(*temp)[8]);
void update_attack(int(*attack)[8], int i, int k);
void ini_att_que(int (*attack)[8], char (*queen)[8]);
void backtrack(int n, int(*attack)[8], char(*queen)[8]);
int counts;
int main()
{

	int attack[8][8];
	char queen[8][8];
	ini_att_que(attack, queen);
	backtrack(0, attack, queen);
	cout << "八皇后问题一共有" << counts << "种解法。" << endl;
	return 0;

}
void ini_att_que(int (*attack)[8], char (*queen)[8])
{
	for (int i = 0; i < 64; i++)
		*(*attack + i) = 0;
	for (int i = 0; i < 64; i++)
		*(*queen + i) = '#';
}
void backtrack(int n, int(*attack)[8], char(*queen)[8])//n为行数
{
	if (n == 8)
	{
		for (int i = 0; i < 8; i++)
		{
			for (int k = 0; k < 8; k++)
				printf("%  c  ", queen[i][k]);
			cout << endl;
		}
		printf("=====================================\n");
		counts++;
		return;
	}
	for (int col = 0; col < 8; col++)//col即column,列数
	{
		if (attack[n][col] == 0)
		{
			int temp[8][8];
			copy_attack(attack,temp);//备份attack数组
			queen[n][col] = 'Q';//放置皇后;
			update_attack(attack, n, col);
			backtrack(n + 1, attack, queen);//检测下一行
			copy_attack(temp, attack);//这里不是备份了!而是撤销之前的update_attack!此处不能直接attack=temp!因为temp是局部变量!函数结束后会被销毁(即需要深拷贝而不是浅拷贝)
			queen[n][col] = '#';     //撤销之前放置的皇后
		}
	}
	
}
void copy_attack(int(*attack)[8],int(*temp)[8])
{
	for (int i = 0; i < 8; i++)
	{
		for (int k = 0; k < 8; k++)
			temp[i][k] = attack[i][k];
	}
}
void update_attack(int(*attack)[8],int i,int k)//i为行,k为列
{
	for (int m = 1; m < 8; m++)
	{
		for (int g = 0; g < 8; g++)
		{
			int nx = i + m * dir_x[g];//nx和ny是被攻击的地方,利用方向数组直接向八个方向辐射!
			int ny = k + m * dir_y[g];
			if (nx >= 0 && nx < 8 && ny >= 0 && ny < 8)
			{
				attack[nx][ny] = 1;
			}
		}
	}
}
//思路来源:https://www.bilibili.com/video/BV1ZK411K7A8?spm_id_from=333.999.0.0 (务必反复看,讲得很清楚)
/*
* 视频中使用vector来储存每次尝试的结果;需要注意的是,vector本质是new开辟的,而上面代码的实现
  并未使用new开辟空间,而是采用的临时数组,所以撤销操作时,需要"深度拷贝",否则函数返回后,数组将失效!

*/

posted @   QuanHa  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示