用于求最优解、一组解、求全部解这类问题
从问题的某一种可能出发,搜索从这种情况出发所能达到的所有可能,如果有路可以走下去,就走到下一个状态,继续按照这种规则搜索;当这条路走到“尽头”而没有达到目标状态的时候,在倒回上一个出发点,从另一个可能出发,继续搜索,直到达到目标状态。
回溯与递归的区别
递归是一种算法结构,递归会出现在子程序中自己调用自己或间接地自己调用自己。
回溯是一种算法思想, 从问题的某一种可能出发, 搜索从这种情况出发所能达到的所有可能, 当这一条路走到” 尽头 “的时候, 再倒回出发点, 从另一个可能出发, 继续搜索. 这种不断” 回溯 “寻找解的方法。
通俗点讲回溯就是一种试探,类似于穷举,但回溯有“剪枝”功能,比如求和问题。给定7个数字,1 2 3 4 5 6 7求和等于7的组合,从小到大搜索,选择1+2+3+4 =10>7,已经超过了7,之后的5 6 7就没必要在继续了,这就是一种搜索过程的优化。
走迷宫问题
给一迷宫表个和入口位置,找出并打印出从入口到出口的路径
public class Zoumigong {
public static void main(String[] args) {
//小球从(1,1)出发,到达(6,5)结束
//值为0表示没走过,值为2表示通路,值为3表示走过(测试过),但是不通
//在走迷宫时,尝试方向 下右上左,走不通,则回溯
int[][] map=new int[8][7];
migong(map);
for (int[] ints : map) {
for (int anInt : ints) {
System.out.print(" "+anInt);
}
System.out.println();
}
setWay(map,1,1);
System.out.println("走出之后的");
for (int[] ints : map) {
for (int anInt : ints) {
System.out.print(" "+anInt);
}
System.out.println();
}
}
//生成地图
public static void migong(int[][] map){
//用1当墙
for (int i = 0; i < 7; i++) {
map[0][i]=1;
map[7][i]=1;
}
for (int i = 0; i < 8; i++) {
map[i][6]=1;
map[i][0]=1;
}
//设置挡板
map[3][1]=1;map[3][2]=1;
}
//寻求出路 下右上左
public static boolean setWay(int[][] map,int i,int j){
if (map[6][5]==2){//找到出路
return true;
}
else {
if(map[i][j]==0){
map[i][j]=2;//假设为通路上一点
//按照下右上左开始尝试
if (setWay(map, i+1,j)){
return true;
}
else if (setWay(map, i,j+1)){
return true;
}
else if (setWay(map, i-1,j)){
return true;
}
else if (setWay(map, i,j-1)){
return true;
}
else{//说明该点不通
map[i][j]=3;
return false;
}
}
else {//该点为1,2,3
return false;
}
}
}
}
八皇后问题
8x8的棋盘 有八个皇后 要求任意两个皇后都不能处于同一行,同一列或同一斜线上,有多少种解法
//8x8的棋盘 有八个皇后 要求任意两个皇后都不能处于同一行,同一列或同一斜线上(92种结果,判断15720次)
// 使用一维数组:arr[i]=val 表示第i+1个皇后要放在第i+1行的第val+1列,
public class bahuanghou {
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.check(0);
System.out.println(queue8.count);
System.out.println(queue8.panduancount);
}
}
class Queue8{
int max=8;
int[] array=new int[max];
int count=0;
int panduancount=0;
//check每一次递归时,都有八次循环,循环结束,回溯到上层
public void check(int n){//放置第n个皇后
if(n==max){//8个都放置完毕
print();
return;
}
//
for (int i = 0; i < max; i++) {
array[n]=i;
if(panduan(n)){//判断位置是否冲突
check(n+1);//摆放下一个
}
//冲突就进入下一次循环,相当于把列后移了一次
}
}
public boolean panduan(int n){//n为第n个皇后
panduancount++;
for (int i = 0; i < n; i++) {//i,n不同 皇后不可能同行
//不同列+不同斜线(y=x;y=-x)
if(array[i]==array[n]||(Math.abs(array[i]-array[n])==Math.abs(i-n))) {
return false ;
}
}
return true;
}
public void print(){
count++;
System.out.println(Arrays.toString(array));
System.out.println();
}
}