07 八皇后问题
来源:互联网 发布:mssql语句转mysql 编辑:程序博客网 时间:2024/05/17 06:35
前言
无
问题描述
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。
– 来自百度百科
思路
思路 : 此处的实现为递归实现, 使用一个boolean[] 来维护当前皇后可落子的位置, 然后进行穷举各个可用位置, 并递归下一个皇后的可落子位置, 当遍历深度为maxDepth[皇后的个数]的时候, 打印结果
参考代码
/** * file name : Test12EightQueue.java * created at : 10:33:20 AM Jun 8, 2015 * created by 970655147 */package com.hx.test05;public class Test12EightQueue { // 八皇后问题 public static void main(String args[]){ // 1. // Queen8 queen = new Queen8();// //核心函数// queen.getArrangement(0);// System.out.print("\r\n");// System.out.println(queen.MAXQUEEN+"皇后问题有"+queen.num+"种摆放方法。"); // 2. eightQueen(); } // 八皇后问题, 初始化queenNum, queenPos, isRowAvail, planNum private static void eightQueen() { int queenNum = 8; int[] queenPos = new int[queenNum]; boolean[] isRowAvail = new boolean[queenNum]; planNum = 0; getForN(queenPos, 0, queenNum, isRowAvail);// getForN02(queenPos, 0, queenNum); } // 获取第depth个王后的位置 // updateRowAvail更新第depth个王后可能的位置, 然后设置王后可能的位置 // 如果不行的话 回溯 再次设置 static int planNum = 0; private static void getForN(int[] queenPos, int depth, int maxDepth, boolean[] isRowAvail) { if(depth == maxDepth) { planNum ++; printResult(queenPos, planNum); return ; } // 待优化 for(int i=0; i<maxDepth; i++) { updateRowAvail(queenPos, depth, maxDepth, isRowAvail); if(isRowAvail[i] ) { queenPos[depth] = i; getForN(queenPos, depth+1, maxDepth, isRowAvail); } } } // 思路和上面基本一致, 这里是以空间换时间, 降低了时间开销 private static void getForN02(int[] queenPos, int depth, int maxDepth) { if(depth == maxDepth) { planNum ++; printResult(queenPos, planNum); return ; } boolean[] isRowAvail = new boolean[queenPos.length]; updateRowAvail(queenPos, depth, maxDepth, isRowAvail); for(int i=0; i<maxDepth; i++) { if(isRowAvail[i] ) { queenPos[depth] = i; getForN02(queenPos, depth+1, maxDepth); } } } // 根据位置关系, 打印出王后的摆放位置 public static void printResult(int[] queenPos, int num){ int max = queenPos.length; Log.log("第 " + num + " 种走法 : "); for(int i=0;i<max;i++){ for(int j=0;j<max;j++){ if(i == queenPos[j]){ Log.logWithoutLn("o "); }else Log.logWithoutLn("x "); } Log.enter(); } } // 更新isRowAvail 检查前面的已经确定的位置, 设置下一列的可行性 // 首先 设置isRowAvail所有的元素为true // 接着 遍历queenPos中depth之前的元素 更新isRowAvail[将不可落子的地方设置为false] private static void updateRowAvail(int[] queenPos, int depth, int maxDepth, boolean[] isRowAvail) { setAllTure(isRowAvail); for(int i=0; i<depth; i++) { isRowAvail[queenPos[i]] = false; int off = depth - i; if((queenPos[i] + off) < maxDepth) { isRowAvail[queenPos[i] + off] = false; } if((queenPos[i] - off) >= 0) { isRowAvail[queenPos[i] - off] = false; } } } // 设置该boolean[] 所有的元素为true public static void setAllTure(boolean []isRowAvail) { for(int i=0; i<isRowAvail.length; i++) { isRowAvail[i] = true; } } // 八皇后问题, 来自 : http://blog.csdn.net/zhong317/article/details/4586131 static class Queen8 { public static int num = 0; //累计方案总数 public static final int MAXQUEEN = 8;//皇后个数,同时也是棋盘行列总数 public static int[] cols = new int[MAXQUEEN]; //定义cols数组,表示8列棋子摆放情况 public Queen8() { } public void getArrangement(int n){ //遍历该列所有不合法的行,并用rows数组记录,不合法记为rows[i]=true boolean[] rows = new boolean[MAXQUEEN]; for(int i=0;i<n;i++){ rows[cols[i]]=true; int d = n-i; if(cols[i]-d >= 0) { rows[cols[i]-d]=true; } if(cols[i]+d <= MAXQUEEN-1) { rows[cols[i]+d]=true; } } for(int i=0;i<MAXQUEEN;i++){ //判断该行是否合法 if(rows[i]) continue; //设置当前列合法棋子所在行数 cols[n] = i; //当前列不为最后一列时 if(n<MAXQUEEN-1){ getArrangement(n+1); }else{ //累计方案个数 num++; //打印棋盘信息 printChessBoard(); } } } public void printChessBoard() { System.out.print("第"+num+"种走法 \r\n"); for(int i=0;i<MAXQUEEN;i++){ for(int j=0;j<MAXQUEEN;j++){ if(i==cols[j]){ System.out.print("0 "); }else System.out.print("+ "); } System.out.print("\r\n"); } } }}
效果截图
总结
一个很经典的问题, 记得曾经我看一本C++参考书中就有这个算法, 还有一个映像比较深的是 蛇形数组
这里使用的是递归, 当然可以改写位循环结构, 不过 会臃肿一点
参考
http://blog.csdn.net/zhong317/article/details/4586131
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!
0 0
- 07 八皇后问题
- 八皇后 n皇后 问题
- 八皇后N皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题(2)
- 八皇后问题(3)
- 八皇后问题
- 八皇后问题程序
- 浅谈八皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题求解
- 八皇后问题
- 八皇后问题
- 性能调优从哪方面入手?
- 批量kill mysql线程和输出完整info mysql线程
- MFC画图
- 内存分区
- 开源日志系统比较
- 07 八皇后问题
- jsp页面提交中文到MySql数据库乱码
- Visual C++ 2008 SP1 MFC (OFFICE界面)使用入门
- Swift 基本知识点之一基本概念
- Parcelable用法。
- CWnd与HWND的区别与转换
- RAM的分类
- 野指针
- Linux下profile和bashrc四种的区别