9.7例题:八皇后问题

问题描述:

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

代码示例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; }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值