回溯算法
基本思路
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
代码格式
private void backtrack("原始参数") {
// 终止条件(递归必须要有终止条件)
if ("终止条件") {
// 一些逻辑操作(可有可无,视情况而定)
return;
}
for (int i = "for循环开始的参数"; i < "for循环结束的参数"; i++) {
//一些逻辑操作(可有可无,视情况而定)
//做出选择
//递归
backtrack("新的参数");
//一些逻辑操作(可有可无,视情况而定)
//撤销操作
}
}
四皇后问题
其实最经典的是八皇后问题,但是分析起来比较麻烦,所以就通过四皇后来透析一些有关皇后问题,麻雀虽小,五脏俱全嘛。
- 思路:
1.指定一个位置
2.指定第二个位置时,判断该位置是否可放,可放进行下一行,否则回到步骤1
3.直到最后一行有可放位置
在全局定义一个static int 类型的count变量用于记录有多少中不同的存放类型。
判断该位置是否可存放皇后Q
/**
* 判断该位置是否可存放皇后
* @param queen 数组
* @param row 行
* @param col 列
* @return
*/
private boolean isVaild(char[][] queen, int row, int col) {
// 先判断上面是否有没有已经置Q的位置
for(int i=row-1;i>=0;i--) { //此位置的上面,列不变向上找行
if(queen[i][col]=='Q') { //一旦发现
return false; //此位置不能放
}
}
// 在判断右上的位置是否有Q
for(int i=row-1 ,j=col+1;i>=0 &&j<queen[0].length;i--,j++) { //此位置的右上方行要减1,列要加1
if(queen[i][j]=='Q') {
return false;
}
}
// 最后判断左上的位置是否有Q
for(int i =row-1,j=col-1;i>=0&&j>=0;i--,j--) { //此位置的左上方行要减一列也要减一
if(queen[i][j] =='Q') {
return false;
}
}
// 如果都没找到,那么说明没有,此位置是可以存放的
return true;
}
打印数组
/**
* 打印数组
* @param queen
*/
private void printQueen(char[][] queen) {
for(int i = 0 ; i < queen.length ; i ++ ){
for(int j = 0 ; j < queen.length ; j++){
System.out.print(queen[i][j]);
}
System.out.println();
}
}
初始化数组
/**
* 初始化数组
* @param queen
*/
private void initializeQueen(char[][] queen) {
for(int i = 0 ; i < queen.length ; i ++ ){
for(int j = 0 ; j < queen.length ; j++){
queen[i][j]='A';
}
}
}
回溯算法
/**
* 求二维数组中皇后存放方法
* @param queen 数组
* @param row 行
*/
public void queen(char[][] queen, int row) {
// 结束条件:即当cow为数组的长度时结束
if (row == queen.length) {
count++;
//自己写的一个公共方法,打印二维数组的,
printQueen(queen);
System.out.println();
return;
}
for (int col = 0; col < queen.length; col++) {
//验证当前位置是否可以放皇后
if (isVaild(queen, row, col)) {
//如果在当前位置放一个皇后不冲突,就在当前位置放一个皇后
queen[row][col] = 'Q';
//递归,在下一行继续……
queen(queen, row + 1);
//撤销当前位置的皇后
queen[row][col] = 'A';
}
}
}
main测试
/**
* main方法测试
* @param args
*/
public static void main(String[] args) {
char [][] chars = new char[4][4];
Queen q = new Queen();
q.initializeQueen(chars);
q.queen(chars,0);
System.out.println("总共有:"+count+"种不同的放置方法!");
}
}
测试结果
AQAA
AAAQ
QAAA
AAQA
AAQA
QAAA
AAAQ
AQAA
总共有:2种不同的放置方法!