八皇后问题及n皇后问题解法及效率优化笔记(1)
2018-03-14 16:12
615 查看
八皇后问题是一个很有趣的问题,话说,有一个八行八列的棋盘,有八个皇后棋子,这八个棋子摆在这八行八列的棋盘上,且行列斜线都不能重合,由此,推及到n皇后问题。
八皇后的程序效率问题是一个相当值得研究的问题,程序效率的高低和程序算法密切相关,由此,研究程序效率最后变成了算法的研究。有人将类似追求效率极致的编程称为极限编程。
一个问题的解法千千万,但效率最好的却不好发现。
下面,是我关于八皇后及n皇后问题解法的第一版,初始版,也为了循序渐进,效率不高,代码没有使用多线程,全靠一个主线程在浪!
代码如下:/****
* 八皇后问题解法(皇后 不同行 不同列 不同斜线)
*
* @author wjw
*
* @since 2018-03-14
*/
public class EightQueenQuestion {
private static final int HAS_CHESSMAN = 1;//有皇后棋子标志
private static final int NO_CHESSMAN = 0;//无皇后棋子标志
//初始化全局计数器
private static long count = 0;
public static void main(String[] args) {
//初始化棋盘(从8皇后)
int n = 8;
for (int i = n; i < 20; i++) {
long beginTime = System.currentTimeMillis();
int[][] chessBoard = initChessBoard(i);
setChessBoard(chessBoard,0);
System.out.println(i + "皇后问题共有符合条件排列方式 " + count + "种,耗时" + (System.currentTimeMillis() - beginTime) + "ms");
count = 0;//计数器归0
}
}
/*****
* 初始化空棋盘
* @param n
* @return
*/
public static int[][] initChessBoard(int n){
int[][] chessBoard = new int
;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
chessBoard[i][j] = NO_CHESSMAN;
}
}
return chessBoard;
}
/******
* 设置棋盘棋子位置 + 检验棋子位置是否合格
* @param chessBoard
* @param line
* @return
*/
public static void setChessBoard(int[][] chessBoard, int line){
for(int i = 0; i < chessBoard.length; i++) {
chessBoard[line][i] = HAS_CHESSMAN;
if(line == chessBoard.length -1){
if(check(chessBoard)){
//printQueue(chessBoard);
count++;
}
}else{
setChessBoard(chessBoard, line + 1);
}
_refreshHorizontal(chessBoard, line);
}
}
/******
* 检验当前n皇后排列方式是否合格
* @param queue n皇后排列方式
* @return
*/
public static boolean check(int[][] queue){
int n = queue.length;
long horizontalResult = 0;
long verticalResult = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//左右不同斜线
if(queue[i][j] == HAS_CHESSMAN){
/*****
* 验证左斜线
* *
* *
* ******
*/
if(j > 0 && i < n - 1){
if(!_leftCompare(i, j, queue))
return false;
}
/*****
* 验证右斜线
* *
* *
* ******
*/
if(j < n - 1 && i < n -1){
if(!_rightCompare(i, j, queue))
return false;
}
}
//分别计算横纵向和
horizontalResult += queue[i][j];
verticalResult += queue[j][i];
//横向结果或纵向结果和大于1,表示该行有多于一个皇后,不符合条件
if(horizontalResult > 1 || verticalResult > 1){
return false;
}
}
//换行归0
horizontalResult = 0;
verticalResult = 0;
}
return true;
}
/******
* 递归左比较
* @param i
* @param j
* @param queen
* @return
*/
private static boolean _leftCompare(int i,int j, int[][] queue){
if(j == 0 || i == queue.length -1){
//左比较,比较到最左边或最下边仍然没有棋子,返回true
return true;
}
if(queue[i+1][j-1] == HAS_CHESSMAN)
return false;
return _leftCompare(i+1, j-1, queue);
}
/******
* 递归右比较
* @param i
* @param j
* @param queen
* @return
*/
private static boolean _rightCompare(int i,int j, int[][] queen){
if(i == queen.length - 1 || j == queen.length - 1){
//右比较,比较到最右边或最下边仍然没有棋子,返回true
return true;
}
if(queen[i+1][j+1] == HAS_CHESSMAN)
return false;
return _rightCompare(i+1, j+1, queen);
}
/*****
* 排列组合计算共有多少种排列方式
* @para
a6c0
m n
* @return
*/
public static long chessBoardNum(int n){
long tempUpNum = 1;
long tempDownNum = 1;
for (int i = 0; i < n; i++) {
tempUpNum *= n * n - i;
tempDownNum *= n - i;
}
return tempUpNum / tempDownNum;
}
/****
* 恢复棋盘第n行
* @param chessBoard
* @param n 待恢复复行数
*/
private static void _refreshHorizontal(int[][] chessBoard, int n){
for (int i = 0; i < chessBoard.length; i++) {
chessBoard
[i] = 0;
}
}
/*****
* 打印当前棋盘
* @param chessBoard
*/
public static void printQueue(int[][] chessBoard){
int n = chessBoard.length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(chessBoard[i][j] + " ");
}
System.out.println("\r\n");
}
System.out.println("\r\n");
}
}
运行结果如下:
8皇后问题共有符合条件排列方式 92种,耗时899ms
9皇后问题共有符合条件排列方式 352种,耗时22073ms
10皇后问题共有符合条件排列方式 724种,耗时694752ms
从运行结果看,效率很慢,第一版,为以后提供了很大的优化空间啊
待续...
如有错误,欢迎指正
end
八皇后的程序效率问题是一个相当值得研究的问题,程序效率的高低和程序算法密切相关,由此,研究程序效率最后变成了算法的研究。有人将类似追求效率极致的编程称为极限编程。
一个问题的解法千千万,但效率最好的却不好发现。
下面,是我关于八皇后及n皇后问题解法的第一版,初始版,也为了循序渐进,效率不高,代码没有使用多线程,全靠一个主线程在浪!
代码如下:/****
* 八皇后问题解法(皇后 不同行 不同列 不同斜线)
*
* @author wjw
*
* @since 2018-03-14
*/
public class EightQueenQuestion {
private static final int HAS_CHESSMAN = 1;//有皇后棋子标志
private static final int NO_CHESSMAN = 0;//无皇后棋子标志
//初始化全局计数器
private static long count = 0;
public static void main(String[] args) {
//初始化棋盘(从8皇后)
int n = 8;
for (int i = n; i < 20; i++) {
long beginTime = System.currentTimeMillis();
int[][] chessBoard = initChessBoard(i);
setChessBoard(chessBoard,0);
System.out.println(i + "皇后问题共有符合条件排列方式 " + count + "种,耗时" + (System.currentTimeMillis() - beginTime) + "ms");
count = 0;//计数器归0
}
}
/*****
* 初始化空棋盘
* @param n
* @return
*/
public static int[][] initChessBoard(int n){
int[][] chessBoard = new int
;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
chessBoard[i][j] = NO_CHESSMAN;
}
}
return chessBoard;
}
/******
* 设置棋盘棋子位置 + 检验棋子位置是否合格
* @param chessBoard
* @param line
* @return
*/
public static void setChessBoard(int[][] chessBoard, int line){
for(int i = 0; i < chessBoard.length; i++) {
chessBoard[line][i] = HAS_CHESSMAN;
if(line == chessBoard.length -1){
if(check(chessBoard)){
//printQueue(chessBoard);
count++;
}
}else{
setChessBoard(chessBoard, line + 1);
}
_refreshHorizontal(chessBoard, line);
}
}
/******
* 检验当前n皇后排列方式是否合格
* @param queue n皇后排列方式
* @return
*/
public static boolean check(int[][] queue){
int n = queue.length;
long horizontalResult = 0;
long verticalResult = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//左右不同斜线
if(queue[i][j] == HAS_CHESSMAN){
/*****
* 验证左斜线
* *
* *
* ******
*/
if(j > 0 && i < n - 1){
if(!_leftCompare(i, j, queue))
return false;
}
/*****
* 验证右斜线
* *
* *
* ******
*/
if(j < n - 1 && i < n -1){
if(!_rightCompare(i, j, queue))
return false;
}
}
//分别计算横纵向和
horizontalResult += queue[i][j];
verticalResult += queue[j][i];
//横向结果或纵向结果和大于1,表示该行有多于一个皇后,不符合条件
if(horizontalResult > 1 || verticalResult > 1){
return false;
}
}
//换行归0
horizontalResult = 0;
verticalResult = 0;
}
return true;
}
/******
* 递归左比较
* @param i
* @param j
* @param queen
* @return
*/
private static boolean _leftCompare(int i,int j, int[][] queue){
if(j == 0 || i == queue.length -1){
//左比较,比较到最左边或最下边仍然没有棋子,返回true
return true;
}
if(queue[i+1][j-1] == HAS_CHESSMAN)
return false;
return _leftCompare(i+1, j-1, queue);
}
/******
* 递归右比较
* @param i
* @param j
* @param queen
* @return
*/
private static boolean _rightCompare(int i,int j, int[][] queen){
if(i == queen.length - 1 || j == queen.length - 1){
//右比较,比较到最右边或最下边仍然没有棋子,返回true
return true;
}
if(queen[i+1][j+1] == HAS_CHESSMAN)
return false;
return _rightCompare(i+1, j+1, queen);
}
/*****
* 排列组合计算共有多少种排列方式
* @para
a6c0
m n
* @return
*/
public static long chessBoardNum(int n){
long tempUpNum = 1;
long tempDownNum = 1;
for (int i = 0; i < n; i++) {
tempUpNum *= n * n - i;
tempDownNum *= n - i;
}
return tempUpNum / tempDownNum;
}
/****
* 恢复棋盘第n行
* @param chessBoard
* @param n 待恢复复行数
*/
private static void _refreshHorizontal(int[][] chessBoard, int n){
for (int i = 0; i < chessBoard.length; i++) {
chessBoard
[i] = 0;
}
}
/*****
* 打印当前棋盘
* @param chessBoard
*/
public static void printQueue(int[][] chessBoard){
int n = chessBoard.length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(chessBoard[i][j] + " ");
}
System.out.println("\r\n");
}
System.out.println("\r\n");
}
}
运行结果如下:
8皇后问题共有符合条件排列方式 92种,耗时899ms
9皇后问题共有符合条件排列方式 352种,耗时22073ms
10皇后问题共有符合条件排列方式 724种,耗时694752ms
从运行结果看,效率很慢,第一版,为以后提供了很大的优化空间啊
待续...
如有错误,欢迎指正
end
相关文章推荐
- 使用位运输优化的n皇后问题解法
- N-Queens N皇后问题 深搜 关于效率优化(重重)
- n皇后问题(位运算优化)
- Mysql学习笔记八,Mysql优化篇,常用sql技巧和常见问题
- N皇后问题优化
- 优化算法 | N皇后问题启发式算法局部搜索
- TXT格式的Excel表格读取问题优化解法(目前我所知的最简洁算法)
- Java笔记(一)--Eclipse 操作MySQL数据库的效率问题
- N皇后问题 位运算解法【JAVA实现】
- [转]Android笔记: android APP 内存与速度的优化问题
- 01背包问题(当有的背包重量是非整数时)的递归(优化成动态规划+再用滚动数组优化)解法+一些动态规划(递归,搜索)的高级技巧
- 精确覆盖问题学习笔记(五)——优化算法的实现代码
- N皇后问题解法及解的个数
- 程序员面试金典(动态规划):8(n)皇后问题(java解法)
- 八皇后问题(递归解法)
- SQL Server中的SQL语句优化与效率问题
- python数据结构学习笔记-2017-01-08-01-N皇后问题、迷宫问题和跳马问题的递归解决
- n皇后问题纯数组解法
- 4.指派问题匈牙利解法以及其优化
- 关于数据库优化2——关于表的连接顺序,和where子句的前后顺序,是否会影响到sql的执行效率问题