八皇后问题

八皇后问题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

/*
	Name: 八皇后问题
	Copyright: 
	Author: Zhang Kewei
	Date: 20/03/19 16:17
	Description: 一个古老而著名的问题,非常经典 
*/

/*
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。
该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格
的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后
都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯
认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种
不同的解,后来有人用图论的方法解出92种结果。
*/ 
#include <bits/stdc++.h> 
using namespace std;

#define queen -1 
int queen_8[8][8] = {0};//8*8棋盘,放置皇后的位置标记为-1 
int ans_queen_8 = 0;//八皇后问题解的种数 

//在(x,y)处放置皇后,并标记皇后能够吃到的位置 
//写得比较啰嗦,但逻辑简单,易懂 
void put_down_the_queen(int x,int y) 
{
	for(int i = 0;i<8;i++)//标记行 
		queen_8[x][i]+=1;
	for(int i = 0;i<8;i++)//标记列 
		queen_8[i][y]+=1;
	for(int i=x,j=y;;)//标记左上 
	{ 
		i--;j--;
		if(i>=0&&j>=0)
			//因为该位置的棋子可能能够被多个王后吃掉 ,下同 
			queen_8[i][j]+=1;
		else
			break;
	}
	
	for(int i=x,j=y;;)//标记右上 
	{
		i++;j--;
		if(i<8&&j>=0)
			queen_8[i][j]+=1;
		else
			break;
	}
	
	for(int i=x,j=y;;)//标记左下 
	{
		i--;j++;
		if(i>=0&&j<8)
			queen_8[i][j]+=1;
		else
			break;
	}
	
	for(int i=x,j=y;;)//标记右下 
	{
		i++;j++;
		if(i<8&&j<8)
			queen_8[i][j]+=1;
		else
			break;
	}
	queen_8[x][y] = queen;//放置皇后 
}

//拿走在(x,y)的皇后,并取消皇后能够吃到的位置的标记
//写得比较啰嗦,但逻辑简单,易懂 
void pick_up_the_queen(int x,int y)
{
	for(int i = 0;i<8;i++)//取消标记行 
		queen_8[x][i]-=1;
	for(int i = 0;i<8;i++)//取消标记列 
		queen_8[i][y]-=1;
	
	for(int i=x,j=y;;)//取消左上标记 
	{
		i--;j--;
		if(i>=0&&j>=0)
			queen_8[i][j]-=1;
		else
			break;
	}
	
	for(int i=x,j=y;;)//取消右上标记 
	{
		i++;j--;
		if(i<8&&j>=0)
			queen_8[i][j]-=1;
		else
			break;
	}
	
	for(int i=x,j=y;;)//取消左下标记
	{
		i--;j++;
		if(i>=0&&j<8)
			queen_8[i][j]-=1;
		else
			break;
	}
	
	for(int i=x,j=y;;)//取消右下标记 
	{
		i++;j++;
		if(i<8&&j<8)
			queen_8[i][j]-=1;
		else
			break;
	}
	queen_8[x][y] = 0;//将皇后拿走 
}


//dfs放置皇后,八个皇后一定每行一个,依次放置每一行 
void dfs_queen_8(int row)
{
	//入过0--7行都已经放进去则一定符合规则(因为只有满足条件才往里面放) 
	if(row==8)
	{
		ans_queen_8++;
		return; 
	}
	else
	{
		for(int column = 0;column<8;column++)//检测每一列 
		{
			//能放(位置没有被占用,也没有其他的皇后能吃掉该位置的棋子)
			if(queen_8[row][column]==0) 
			{
				put_down_the_queen(row,column);//放置皇后,标记该皇后所能到达的所有位置 
				dfs_queen_8(row+1);//放,下一行 
				pick_up_the_queen(row,column);//回溯取消标记 
			}
			//进行下一测尝试,直到尝试完所有可能 
		}	
	}
} 

int main()
{
	dfs_queen_8(0);
	cout<<ans_queen_8;
	return 0;
}

/*
附:
//dfs算法框架 
dfs(状态) 
	-if 状态 是 目标状态then
		dosomething
	-else
		for 每个新状态
			-if 新状态合法
				dfs(新状态)
主程序:
dfs(初始状态)
*/ 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值