标签:分解 方法 nbsp set 测试 can bool 攻击 rac
经典的八皇后问题,
queen 可以攻击的范围: 水平,垂直,斜向, 放置 queen 让所有的queens 不在对方的攻击范围内,问有多少种方法或者产生相应的棋盘。
分析: 依次产生每一行的结果, 先在某行某个位置放一个结果,如果不能产生解 则back tracking 到上一行,重新放置。
以 n=4 为例,每个位置都得分解 n=4 份, 算法复杂度为 n^n ,是一个很高的结果,因此当 n>12 时,测试用例都会TLE。
需要解决的问题:
1. 如果存储 每个位置, 可以定义一个Node {int i, int j} 来标记index, 也可以 在二维矩阵中 用 i*n +j 来唯一的标志位置,只是每次需要 用除法和mod 来计算 i, j 。
给出一个代码, 但代码只排到 10%左右, 需要进一步优化:
class Solution { public List<List<String>> solveNQueens(int n) { List<List<Integer>> result = new ArrayList<>(); dfs(new ArrayList<>(), result,0,n); return generate_results(result,n); } private List<List<String>> generate_results(List<List<Integer>> result,int n){ StringBuilder init_str = new StringBuilder(); for(int i=0; i<n; i++){ init_str.append("."); } //System.out.println(init_str); List<List<String>> re_resu = new ArrayList<>(); for(List<Integer> cur: result){ List<String> cur_str = new ArrayList<>(); for(int val: cur){ int j = val%n; init_str.setCharAt(j,‘Q‘); cur_str.add(init_str.toString()); //System.out.println(cur_str); init_str.setCharAt(j,‘.‘); } re_resu.add(new ArrayList<>(cur_str)); } return re_resu; } private void dfs(List<Integer> curResult, List<List<Integer>> result, int rows,int n){ if(curResult.size() == n){ result.add(new ArrayList<>(curResult)); //System.out.println(curResult); return ; } if(rows>=n) return; for(int i=0; i<n; i++){ int candid = rows*n +i; if(isValid(curResult, candid,n)){ curResult.add(candid); dfs(curResult,result,rows+1,n); curResult.remove(curResult.size()-1); } } } private boolean isValid(List<Integer> curResult, int candid, int n){ int i = candid/n; int j = candid%n; // 水平 and 垂直 for(int cur: curResult){ int cur_i = cur/n; int cur_j = cur%n; if(i == cur_i || j== cur_j) return false; } int x = 0; //斜向:left up for(x =0; x<n; x++){ if(i-x <0 || j-x<0) break; int left_up = (i-x)*n + (j-x); if(curResult.contains(left_up)) return false; } // right down for(x=0; x<n; x++){ if(i+x>=n || j+x >=n) break; int right_down = (i+x)*n + j+x; if(curResult.contains(right_down)) return false; } //right up for(x=0; x<n; x++){ if(i-x<0 || j+x>=n) break; int right_up = (i-x) *n +j+x; if(curResult.contains(right_up)) return false; } //left down for(x=0; x<n; x++){ if(i+x>=n|| j-x<0) break; int left_down = (i+x)*n + j-x; if(curResult.contains(left_down)) return false; } return true; } }
标签:分解 方法 nbsp set 测试 can bool 攻击 rac
原文地址:https://www.cnblogs.com/keepAC/p/9973798.html