您的位置:首页 > 其它

八皇后问题之一(枚举+搜索)

2013-01-22 20:07 399 查看
问题描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如

何将8 个皇后放在棋盘上(有8 * 8 个方格),使它们谁也不能被吃掉!这就是著名的八皇后

问题。 对于某个满足要求的8 皇后的摆放方法,定义一个皇后串a 与之对应,即a=b1b2...b8,

其中bi 为相应摆法中第i 行皇后所处的列数。已经知道8 皇后问题一共有92 组解(即92 个

不同的皇后串)。给出一个数b,要求输出第b 个串。串的比较是这样的:皇后串x 置于皇

后串y 之前,当且仅当将x 视为整数时比y 小。

输入数据

第 1 行是测试数据的组数n,后面跟着n 行输入。每组测试数据占1 行,包括一个正整

数b(1 <= b <= 92)

输出要求

n 行,每行输出对应一个输入。输出应是一个正整数,是对应于b 的皇后串

输入样例

2

1

92

输出样例

15863724

84136275

解题思路:

我们有一个8*8 的矩阵仿真棋盘标识当前已经摆放好的棋子所控制的区域。

用一个有92 行每行8 个元素的二维数组记录可行的摆放方法。用一个递归程序来实现

尝试摆放的过程。基本思想是假设我们将第一个棋子摆好,并设置了它所控制的区域,

则这个问题变成了一个7 皇后问题,用与8 皇后同样的方法可以获得问题的解。那我们

就把重心放在如何摆放一个皇后棋子上,摆放的基本步骤是:从第1 到第8 个位置,顺

序地尝试将棋子放置在每一个未被控制的位置上,设置该棋子所控制的格子,将问题变

为更小规模的问题向下递归,需要注意的是每次尝试一个新的未被控制的位置前,要将

上一次尝试的位置所控制的格子复原。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int QueenPalce[92][8]; //存放92种皇后棋子的摆放方法
int count = 0;
int bord[8][8];        //模拟棋盘
void putQueen(int ithQueen); //递归函数,每次摆好一颗棋子

int main()
{
freopen("in.txt","r",stdin);
int n,i,j;
for(i=0; i<8; i++)
{
for(j=0; j<8; j++) //棋盘初始化
bord[i][j] = -1;

for(int i=0; i<92; i++) //存放数组初始化
QueenPalce[j][i] = 0;
}
putQueen(0);  //从第零个棋子开始摆放,函数最终目的是生成QueenPlace数组
scanf("%d",&n);  //测试数据格数

for(int i =0; i<n; i++)
{
int ith;  //第i个棋子
scanf("%d",&ith);
for(int j=0; j<8; j++)
printf("%d",QueenPalce[ith-1][j]);//输出第i个棋子的皇后串
printf("\n");
}
return 0;
}

void putQueen(int ithQueen)  //摆放函数
{
int i,k,r;
if(ithQueen == 8)  //如果是第8颗棋子
{
count++;
return;
}
for(i=0; i<8; i++)
{
if(bord[i][ithQueen]==-1) //从第1位置到第8位置顺序尝试
{
bord[i][ithQueen] = ithQueen; //摆放皇后
for(k=count; k<92; k++)
QueenPalce[k][ithQueen] = i+1;//其后的第ith个皇后放在第i+1位上

for(k=0; k<8; k++)   //设置该摆放皇后棋子的控制范围
for(r=0; r<8; r++)
if(bord[k][r]==-1&&(k==i||r==ithQueen||abs(k-i)==abs(r-ithQueen)))
bord[k][r]=ithQueen;

putQueen(ithQueen+1);  //向其后的棋子递归

for(k=0; k<8; k++)  //解除上级棋子的控制范围
for(r=0; r<8; r++)
if(bord[k][r]==ithQueen)
bord[k][r]=-1;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: