zoukankan      html  css  js  c++  java
  • 【LeetCode】51.N皇后(回溯)

    题目链接

    51. N 皇后

    题目描述

    解题思路

    1.经典回溯

    普通八皇后问题只需要求出有多少种可行方案即可,而本题稍微更难一点,还需要把这些可行方案记录并打印。

    之前也说到遇到递归问题,两件分析法宝:画出递归树以及函数栈!本题递归树如下:

    遇到的问题如下

    (1)回溯过程中递归返回条件的判断:如何判断两个皇后是否在一条斜线上?

    一开始打算利用max(x,y)/min(x,y)进行判断,但是由于都是整数除法,存在一些情况是行不通的,遂放弃。

    观察之后,可以发现有以下规律:

    利用两个一维数组分别表示主对角线和副对角线。

    //主对角线,当n=4的时候,一共有7个值,也就是2*n-1个值,因为数组索引必须大于等于0,所以当(x-y)<0的时候,还需要+2*n-1;
    int main_dia[] = new int[2*n-1];
    int counter_dia[] = new int[2*n-1];
    

    (2)回溯代码的细节问题。

    AC代码中,赋值为1的代码必须和for循环结束赋值为0的代码的位置是对称的,也就是要么两个都在for循环内,要么两个代码段都在for循环外,不能一里一外

    AC代码

    class Solution {    
        List<List<String>> ans = new ArrayList<>();
        void dfs(int x,int y,int[] x_valid,int[] y_valid,int[] main_dia,int[] counter_dia,int n,int board[][]){
            if(x == n) return;
            if(x_valid[x]==1) return;
            if(y_valid[y]==1) return;
            if(main_dia[x+y]==1) return;
            if(x-y<0&&counter_dia[x-y+2*n-1]==1) return;
            if(x-y>=0&&counter_dia[x-y]==1) return;
            if(x == n -1){
                List<String> temp = new ArrayList<>();
                board[x][y]=1;
                for(int i = 0; i < n; i++){
                    StringBuffer sb = new StringBuffer();
                    for(int j = 0; j < n; j++){
                        if(board[i][j]==1) sb.append("Q");
                        else sb.append(".");
                    }
                    temp.add(sb.toString());
                }
                ans.add(temp);
            }
            //这段赋值为1的代码必须和for循环结束赋值为0的代码的位置是对称的,也就是要么两个都在for循环内,要么两个代码段都在for循环外,不能一里一外
            x_valid[x]=1;
            y_valid[y]=1;
            main_dia[x+y]=1;
            board[x][y]=1;
            if(x-y<0) counter_dia[x-y+2*n-1] = 1;
            else counter_dia[x-y]=1;
            for(int i = 0; i < n; i++){
                dfs(x+1,i,x_valid,y_valid,main_dia,counter_dia,n,board);
            } 
            x_valid[x]=0;
            y_valid[y]=0;
            board[x][y]=0;
            main_dia[x+y]=0;
            if(x-y<0) counter_dia[x-y+2*n-1] = 0;
            else counter_dia[x-y]=0;
        }
    
        public List<List<String>> solveNQueens(int n) {
            int x_valid[] = new int[n];
            int y_valid[] = new int[n];
            int main_dia[] = new int[2*n-1];
            int counter_dia[] = new int[2*n-1];
            int board[][] = new int[n][n];
            for(int i = 0; i < n; i++){
                dfs(0,i,x_valid,y_valid,main_dia,counter_dia,n,board);
            }
            return ans;
        }
    }
    
  • 相关阅读:
    详解著名的awk Oneliner,第三部分:选择性输出特定行
    显示特定行
    nWave指令
    make 命令
    VIM脚本变量
    terninal 快捷键
    vim 实现begin end 配对 使用matchit插件
    VIM删除重复行
    linux命令--find(1)
    zabbix--创建触发器
  • 原文地址:https://www.cnblogs.com/XDU-Lakers/p/13611255.html
Copyright © 2011-2022 走看看