2754:八皇后
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b 1b 2...b 8,其中b i为相应摆法中第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
-
不好意思,昨天食言了,没有更新博客,因为有点懒惰。今天9月1号了,后天即将返回大连,推免的整个征程只剩下最后不到一个月的时间,因此,行百里者半九十,一定要抓住最后的时间,拼上一把。
-
********************************************
-
八皇后问题,用递归来做,思路我是有的,就是依次尝试各个棋子,使之不与已经摆好的棋子冲突,只不过是否冲突的判断条件我想错了,即A与B不冲突,B与C不冲突,不代表A与C不冲突,我只考虑了相邻两个棋子的情况,而实际上应该从头开始遍历,这里有点像dp中的最长公共子序列的问题,不能仅考虑相邻的情况。
-
#include <stdio.h> int hang[8],ans[92][8],num; void queen(int n); int main() { queen(0); int b,n; scanf("%d",&n); while(n--){ scanf("%d",&b); for(int i=0;i<8;i++){ printf("%d",ans[b-1][i]); } printf("\n"); } } void queen(int n) { int i,j; if(n==8){ for(i=0;i<8;i++){ ans[num][i]=hang[i]+1; } num++; return; } for(i=0;i<8;i++){ //核心 for(j=0;j<n;j++){ if(i==hang[j]||(j-n)==hang[j]-i||(n-j)==hang[j]-i) break; } if(j==n){ hang[n]=i; queen(n+1); } } }
也没有必要转换成字符串的格式再输出,拿整型数组存储就可以了,hang做缓存数组,尽量不要拿ans数组直接操作。 - *****************************************
- 今天9.7,刚刚重新写了一遍八皇后的算法,终于感觉搞懂了一点递归。。真的是调试出成果啊,不亲自调试一下什么也发现不了。重写的这一遍,刚开始递归的核心部分也就是queen中的循环弄错了,必须时刻把握i,j的含义。然后我就一直奇怪一点,n==8之后hang对ans赋完值了,为什么不用把hang的数据清空呢?马上不是要进行下一种情况了吗?本次的数据不会对下一次产生影响吗?显然这时我还没有理解递归的本质。递归实际上就是用来代替循环的,并且是基于 回溯法的,这点我通过调试程序发现的。对于0~7的每一个数(每一行),都会执行queen的核心程序,以期望找到在之前的行填好的条件下,还能有多少可能的结果,回溯是不断试错的过程,这样不行,往回退一步可能就行了(这里所谓“行”就是指在现有条件下能够填满8行,不再回溯而是直接走到return),而这时以前几行的数据是不需要删除的!当所有解都被找到后,queen自然就会结束,不用担心出不去的问题。
-
*******************
-
坚持,而不是打鸡血~