现在的位置: 首页 > 综合 > 正文

9.7例题:八皇后问题

2013年08月14日 ⁄ 综合 ⁄ 共 2475字 ⁄ 字号 评论关闭

问题描述:

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将 
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的皇后串
输入样例 



92 
输出样例 
15863724 
84136275 

代码示例1:

/*
*
*Declaration:The author of <<Accelerated C++>> has wrote in the end of that book: As you look for reading materimal,
 keep in mind that books on the shelf do not make you a better programmer.
 Ultimately, the only way to improve your programming is to write programs.
>这些程序来自一些ACM书籍,作者只为提高编程能力,实现书中例题或练习。如有侵权,请联系作者,作者将立即删除。
*
*联系邮箱:mingxinglai#gmail.com
*
*/

// 回溯法
#include <stdio.h>
#include <math.h>
#include <string.h>

int queenPlaces[92][8]; //存放92种皇后棋子的摆放方法
int count = 0;
int board[8][8];//仿真棋盘
void putQueen( int ithQueen );//递归函数,每次摆放好一个棋子
int main(int argc, char* argv[])
{
	int n, i, j;
	memset( board, -1, sizeof(int) * 8 * 8 );//初始化棋盘
	memset( queenPlaces, 0, sizeof( int ) * 92 * 8 );
	
	putQueen( 0 );
	scanf("%d", &n);
	for( i = 0; i < n; i++ )
	{
		int ith;
		scanf("%d", &ith);
		for( j = 0; j < 8; j++ )
			printf("%d", queenPlaces[ith -1 ][j]);
		puts("");
	}
	return 0;
}

void putQueen( int ithQueen )
{
	int i, k, r;
	if( ithQueen == 8 )
	{
		count ++;
		return;
	}	
	
	for( i = 0; i < 8; i++ )
	{
		if( board[i][ithQueen] == -1)//可以摆放
		{
			board[i][ithQueen] = ithQueen;//摆放皇后
			for( k = count; k < 92; k++ )
				queenPlaces[k][ithQueen] = i + 1;

			//设置控制范围
			for( k = 0; k < 8; k++ )
				for( r = 0; r < 8; r++ )
					if( board[k][r] == -1 && ( k == i || r == ithQueen || fabs( k - i) == fabs( r - ithQueen) ) )
						board[k][r] = ithQueen;
			//向下级递归	
			putQueen( ithQueen + 1 );

			//回溯,撤销控制范围
			for( k = 0; k < 8; k++)
				for( r = 0; r < 8; r++)
					if( board[k][r] == ithQueen) board[k][r] = -1;
		}
	}
		
}

代码示例2:

更直观,简洁,且更容易理解。思路:用一个有8个元素的数组记录已经摆放的棋子摆在什么位置,当要放置一个新的棋子时,只需要判断它与已经放置的棋子之间是否冲突就行了。

/*
*
*Declaration:The author of <<Accelerated C++>> has wrote in the end of that book: As you look for reading materimal,
 keep in mind that books on the shelf do not make you a better programmer.
 Ultimately, the only way to improve your programming is to write programs.
>这些程序来自一些ACM书籍,作者只为提高编程能力,实现书中例题或练习。如有侵权,请联系作者,作者将立即删除。
*
*联系邮箱:mingxinglai#gmail.com
*
*/


#include <stdio.h>

//hang[i] = j 表示第i个皇后放在第j列
int ans[92][8], n, b, i, j, num, hang[8];

void queen( int i )
{
	int j, k;
	if( i == 8 )//一组新的解产生了
	{
		for( j = 0; j < 8; j++)
			ans[num][j] = hang[j] + 1;
		num++;
		return;
	}
	//第i个皇后在第i行有8种选择,需要逐一判断与前面 i - 1 个皇后是否冲突	
	for( j = 0; j < 8; j++)//将当前皇后逐一尝试放在不同的列
	{
		for( k = 0; k < i; k++)//逐一判断i与前面的皇后是否冲突
			if( hang[k] == j || ( k - i ) == ( hang[k] - j) || ( i - k ) == ( hang[k] - j) )
			 break;			

		if( k == i)//放置i,尝试第i + 1 个皇后
		{
			hang[i] = j;
			queen( i + 1 );
		}
	}	
}
int main(int argc, char* argv[])
{
	num = 0;
	queen(0);
	scanf("%d", &n);	
	for( i = 0; i < n; i++ )
	{
		scanf("%d", &b);
		for( j = 0; j < 8; j++ ) 
			printf("%d", ans[ b - 1][j]);
		printf("\n");
	}
	return 0;
}

抱歉!评论已关闭.