巧解八皇后问题
2016-05-10 15:57
429 查看
问题描述:
在8*8的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一个斜线上,文有多少中解法?
问题分析:
如果用暴力求解发,则时间复杂度为:8*8的棋盘,一共有64个位置,有8为皇后,所以本质是将8位皇后放在64个位置上,即从64个位置中选择8个位置。所以总的搜索空间为:C864。
但是这个问题有很多限制条件,我们将这些限制条件加上之后,就可以大大的降低解空间:
同一行中不能放两个皇后,即每行只能放一个皇后。因此我们可以将8*8的矩阵缩减成一个8维的数组,表示一行只能放置一个皇后,其中数组的值表示:a[i] = j表示第i行在第j列上放置一个皇后;
然后我们需要用3个额外的辅助数组来保存列的放置情况,主对角线的放置情况,次对角线的放置情况:
一共8列,因此用一个8维的boolean型数组记录当前列是否有皇后已经放置;
对角线的问题略有复杂,但是仍然可以分析得出横纵坐标之间的关系:假设在我们放置皇后的数组中,a[3] = 2, 也就是说明:
对于主对角线来说:所有a[1][0], a[2][1], a[4][3], a[5][4], a[6][5], a[7][6]不能再放置皇后,可以发现他们横纵坐标的关系为:x-y=1始终成立,因此我们得出如果a[i] = j, 则所有i-j的位置都不能再放置皇后,而对于8*8的棋盘来说,-7<=x-y<=7, 即-(N-1)<=x-y<=N-1, 即 0<=x-y+N-1 <=2N-2,所以申请一个长度为2N-1的数组来记录主对角线的摆放情况;
对于次对角线来说:所有a[0][5], a[1][4], a[2][3], a[4][1], a[5][0]都不能再放置皇后,可以发现他们横纵坐标的关系为:x+y=5始终成立,因此我们得出如果a[i] = j,则所有i+j的位置都不能再放置皇后,而对于8*8的棋盘来说,0<=x+y<=2N-2,所以申请一个长度为2N-1的数组来记录次对角线的摆放情况。
用深度优先搜索的思路,每次走到一条思路或者终点,需要回溯。所以代码为:递归+回溯。
在8*8的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一个斜线上,文有多少中解法?
问题分析:
如果用暴力求解发,则时间复杂度为:8*8的棋盘,一共有64个位置,有8为皇后,所以本质是将8位皇后放在64个位置上,即从64个位置中选择8个位置。所以总的搜索空间为:C864。
但是这个问题有很多限制条件,我们将这些限制条件加上之后,就可以大大的降低解空间:
同一行中不能放两个皇后,即每行只能放一个皇后。因此我们可以将8*8的矩阵缩减成一个8维的数组,表示一行只能放置一个皇后,其中数组的值表示:a[i] = j表示第i行在第j列上放置一个皇后;
然后我们需要用3个额外的辅助数组来保存列的放置情况,主对角线的放置情况,次对角线的放置情况:
一共8列,因此用一个8维的boolean型数组记录当前列是否有皇后已经放置;
对角线的问题略有复杂,但是仍然可以分析得出横纵坐标之间的关系:假设在我们放置皇后的数组中,a[3] = 2, 也就是说明:
对于主对角线来说:所有a[1][0], a[2][1], a[4][3], a[5][4], a[6][5], a[7][6]不能再放置皇后,可以发现他们横纵坐标的关系为:x-y=1始终成立,因此我们得出如果a[i] = j, 则所有i-j的位置都不能再放置皇后,而对于8*8的棋盘来说,-7<=x-y<=7, 即-(N-1)<=x-y<=N-1, 即 0<=x-y+N-1 <=2N-2,所以申请一个长度为2N-1的数组来记录主对角线的摆放情况;
对于次对角线来说:所有a[0][5], a[1][4], a[2][3], a[4][1], a[5][0]都不能再放置皇后,可以发现他们横纵坐标的关系为:x+y=5始终成立,因此我们得出如果a[i] = j,则所有i+j的位置都不能再放置皇后,而对于8*8的棋盘来说,0<=x+y<=2N-2,所以申请一个长度为2N-1的数组来记录次对角线的摆放情况。
用深度优先搜索的思路,每次走到一条思路或者终点,需要回溯。所以代码为:递归+回溯。
package com.eight; import java.util.ArrayList; import java.util.Arrays; class EightQueen { private int N; //The number of queens. private boolean[] column; private boolean[] maind; private boolean[] secondaryd; private ArrayList<int[]> result = new ArrayList<int[]>(); /** * Initial the column, main diagonal, secondary diagonal to false, * which means there is no queen everywhere. * @param N */ public void initQ(int N) { this.N = N; column = new boolean ; maind = new boolean[2 * N - 1]; secondaryd = new boolean[2 * N - 1]; int i = 0; for(i=0; i<column.length; i++) column[i] = false; for(i=0; i<maind.length; i++) maind[i] = false; for(i=0; i<secondaryd.length; i++) secondaryd[i] = false; } /** * the main function of lay queens. */ public void queens() { int[] path = new int ; calcQueen(path, 0); } private void calcQueen(int[] path, int row) { // TODO Auto-generated method stub if(row == N) { result.add(path); System.out.println(Arrays.toString(path)); return; } for(int col=0; col<N; col++) { if(canLay(row, col)) { path[row] = col; column[col] = true; maind[row-col+N-1] = true; secondaryd[row+col] = true; calcQueen(path, row+1); //BackTracking, important!! column[col] = false; maind[row-col+N-1] = false; secondaryd[row+col] = false; } } } /** * Judge if the position can lay a queen. * @param row * @param col * @return */ private boolean canLay(int row, int col) { // TODO Auto-generated method stub return (!column[col] && !secondaryd[row+col] && !maind[row-col+N-1]); } public ArrayList<int[]> getResult() { return result; } } public class Queens { public static void main(String[] args) { EightQueen q = new EightQueen(); q.initQ(8); // It is a eight queens problem. q.queens(); } } //Some output instances: [0, 4, 7, 5, 2, 6, 1, 3] [0, 5, 7, 2, 6, 3, 1, 4] [0, 6, 3, 5, 7, 1, 4, 2] [0, 6, 4, 7, 1, 3, 5, 2] [1, 3, 5, 7, 2, 0, 6, 4] [1, 4, 6, 0, 2, 7, 5, 3] [1, 4, 6, 3, 0, 7, 5, 2] [1, 5, 0, 6, 3, 7, 2, 4] [1, 5, 7, 2, 0, 3, 6, 4] [1, 6, 2, 5, 7, 4, 0, 3] [1, 6, 4, 7, 0, 3, 5, 2] [1, 7, 5, 0, 2, 4, 6, 3] [2, 0, 6, 4, 7, 1, 3, 5]
相关文章推荐
- C# 复制PDF页面到另一个PDF文档
- 删除 Nodejs的方法,记录一下
- 深入剖析JavaScript:Object类型
- thinkPHP
- SQL中union 与union all的用法
- 为什么java的main方法是public static void
- AsyncTask总结
- 进程的描述和进程的创建
- 获取GUID的方法
- anroid不支持CMYK的图片
- google api 3
- BroadcastReceiver要点总结
- 多线程之NSOperation简介
- object-c中类的继承
- POJ 2773 容斥与二分
- zabbix图中中文乱码解决
- c标签
- gtp转换mbr
- 开关电源过流保护-打嗝模式
- Dll注入技术之输入法注入