问题描述
在一个8*8的棋盘内插入8个皇后,使得任意两个不在同一行同一列以及对角线上。
解决思路
将大问题化解为小问题,小问题描述为,前i行已经插入i个皇后,现在第i+1行插入第i+i个皇后。则只需遍历第i+1行上的每一个单元格,并且判断该单元格是否能够插入皇后,若能够插入皇后则将皇后插入相应位置,然后以该棋盘为基础进行第i+2行插入第i+2个皇后的求解,直到i>8后,即表示前8个皇后都以插入棋盘,且没有冲突,此时找到解。
坐标类
package cn.queen;
//位置
public class Post {
int x;
int y;
public Post(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "("+x+","+y+")";
}
}
棋盘类
package cn.queen;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
//棋盘
public class Chessboard {
List<Post> queens;//存皇后位置
int n;//棋盘尺寸
public Chessboard(int n) {
super();
this.n = n;
this.queens = new LinkedList<Post>();
}
//判断是否能在q位置上插入皇后
public boolean canAdd(Post q) {
ListIterator<Post> i = this.queens.listIterator();
while (i.hasNext()) {
Post p = i.next();
//任意两个皇后不能在同一行,同一列和对角线上
if(p.x == q.x||p.y == q.y||Math.abs(q.x-p.x)==Math.abs(q.y-p.y)) {
return false;
}
}
return true;
}
@Override
public String toString() {
return "Chessboard"+this.queens.toString();
}
}
主类
package cn.queen;
/**
* 解决八皇后问题采用分治的思想,将大问题化成若干小问题
*
* */
public class MainClass {
public static int n = 8;//棋盘尺寸
public static Chessboard c = new Chessboard(n);
public static int num = 0;//记录总数
public static void main(String[] args) {
// TODO Auto-generated method stub
trial(0);
}
public static void trial(int i) {
if(i >= n) {//此时前i个皇后位置都以确定,表示n个皇后都以在棋盘内,找到解
num++;
System.out.println(num + "\t= " + c);
return;
}
for(int j = 0;j<n;j++) {//遍历第i行上的所有单元格
Post p = new Post(i+1,j+1);
if(c.canAdd(p)) {//判断在第i行第j列插入皇后时,是否会产生冲突
//System.out.println(new Post(i,j));
c.queens.add(p);//将该位置上插入棋盘
trial(i+1);//因为该位置插入后不产生冲突,所以在此基础之上进行下一行的探索
c.queens.remove(c.queens.size()-1);//进行下一个单元个的探索前,应删除刚刚插入的单元格
}
}
}
}