八皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于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(初始状态)
*/