八皇后,数独(回溯法)

八皇后,数独(回溯法)

1回溯法

回溯法就是,当你面对很多个选择的时候,先随便选一个,做下去,发现不行的时候,再倒回之前选择的情况,重新选择,直到把所有可能性试完。java解决

2,经典八皇后问题

八皇后力扣链接

class Solution {
    public boolean check(int[] arr,int i,int k){
        for(int j=0;j<i;j++){
            if(arr[j]==k||Math.abs(j-i)==Math.abs(arr[j]-k)){
            return false;
        }
        }
        return true;
    }
    public int f(int i,int n,int[] arr){
        int sum=0;
        if(i==n){
            return 1;
        }
        for(int k=0;k<=n-1;k++){
            if(check(arr,i,k)){
                arr[i]=k;
                sum+=f(i+1,n,arr);
            }

        }
        return sum;
    }
    public int totalNQueens(int n) {
        int[] arr=new int[n];
        if(n<=0){
            return 0;
        }
        return f(0,n,arr);
    }
}

1,首先需要数组来记录放过皇后的位置,这里可以采用一维数组,不用二维数组。
因为只是记录格子的两个坐标,不需要记录格子具体的数值。因此,一维数组足够。
2,对于check函数

public boolean check(int[] arr,int i,int k){
        for(int j=0;j<i;j++){
            if(arr[j]==k||Math.abs(j-i)==Math.abs(arr[j]-k)){
            return false;
        }
        }
        return true;
    }

由于是从行开始遍历,所以只需要确认同一列是否有两个皇后和斜线是否有两个皇后。
3,这一步就是回溯过程

for(int k=0;k<=n-1;k++){
     if(check(arr,i,k)){
         arr[i]=k;
        sum+=f(i+1,n,arr);
	}

}

从第i行的第0个元素开始,依次选择

3,数独

class Solution {
    boolean[][] row=new boolean[9][10];
    boolean[][] col=new boolean[9][10];
    boolean[][] area=new boolean[9][10];
    boolean finish=false;
    public void f(char[][] board,int index){
        if(index==81){
            finish=true;
            return;
        }
        int ro=index/9;
        int co=index%9;
        if(board[ro][co]!='.'){
            f(board,index+1);
        }else{
            for(int i=1;i<=9;i++){
            if(!row[ro][i]&&!col[co][i]&&!area[3*(ro/3)+co/3][i]){
                row[ro][i]=true;
                col[co][i]=true;
                area[3*(ro/3)+co/3][i]=true;
                board[ro][co]=(char)(i+'0');
                f(board,index+1);
                if(finish){
                    return;
                }
                row[ro][i]=false;
                col[co][i]=false;
                area[3*(ro/3)+co/3][i]=false;
                board[ro][co]='.';
            }
        }
        
        }



    }
    public void solveSudoku(char[][] board) {
        for(int i=0;i<=8;i++){
            for(int j=1;j<=9;j++){
                row[i][j]=false;
                col[i][j]=false;
                area[i][j]=false;
            }
        }
        for(int i=0;i<=8;i++){
            for(int j=0;j<=8;j++){
                int val=board[i][j]-'0';
                if(board[i][j]!='.'){
                    row[i][val]=true;
                    col[j][val]=true;
                    area[3*(i/3)+(j/3)][val]=true;
                }
            }
        }
        f(board,0);
        return;
    }
}

1,由于数独有行,列以及九宫格的限制
因此需要三个二维数组来分别记录行,列,九宫格的限制

	boolean[][] row=new boolean[9][10];
    boolean[][] col=new boolean[9][10];
    boolean[][] area=new boolean[9][10];

对于row[3][5]=true的意思
row代表行
整句意思是:对于第三行,5这个数字存在

2,开头是初始化三个二维数组

for(int i=0;i<=8;i++){
            for(int j=1;j<=9;j++){
                row[i][j]=false;
                col[i][j]=false;
                area[i][j]=false;
            }
        }
        for(int i=0;i<=8;i++){
            for(int j=0;j<=8;j++){
                int val=board[i][j]-'0';
                if(board[i][j]!='.'){
                    row[i][val]=true;
                    col[j][val]=true;
                    area[3*(i/3)+(j/3)][val]=true;
                }
            }
        }

先全部初始化为false。然后再分别对已经填了数的格子,完善三个二维数组。
3,这一步是如果index这个格子已经填了数,那就跳到下一个格子

if(board[ro][co]!='.'){
            f(board,index+1);
        }else

4,这一步可以通过行和列确定这个格子处于哪一个九宫格(从左上开始数)

3*(row/3)+col/3

5,这一步就是回溯过程

for(int i=1;i<=9;i++){
            if(!row[ro][i]&&!col[co][i]&&!area[3*(ro/3)+co/3][i]){
                row[ro][i]=true;
                col[co][i]=true;
                area[3*(ro/3)+co/3][i]=true;
                board[ro][co]=(char)(i+'0');
                f(board,index+1);

从第index个格子开始,依次尝试1到9个数字,剩下的交给递归

6,一定要记得回溯算法,要还原犯罪现场

		row[ro][i]=false;
        col[co][i]=false;
        area[3*(ro/3)+co/3][i]=false;
        board[ro][co]='.';

这一种情况不行,要把这一种情况造成的影响还原,方便继续尝试后面的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值