您的位置:首页 > 其它

八皇后问题及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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: