N皇后问题

来源:互联网 发布:spss软件应用例子 编辑:程序博客网 时间:2024/04/30 12:28

原题 https://oj.leetcode.com/problems/n-queens/

这个题写了好久。。。

其实思路比较简单。在每一列上按顺序每一个位置放皇后,而前面已经放好的皇后位置对后面放的皇后的位置是有影响的,因此以后选择摆放位置时要遵守前面的约束。

流程基本是:先在第一列选择一个位置放皇后,然后在第二列选择位置时不能和第一列的皇后有冲突(在一条直线或对角线上),在第三列时不能与一二列有冲突,以此类推,直到找到最后一列符合条件的位置,结果记录下来,然后回溯找其他符合条件的位置;或者在第i列时发现没有任何一个位置符合条件,于是需要回溯到第i-1列去,在该列上换下一个位置,继续以上流程。

整个流程类似于深度优先搜索。用栈保存访问过的位置信息,实现回溯。


import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Stack;public class Solution {    private final char INIT = '#';        public static void main(String[] a)    {    for(String[]ss :new Solution().solveNQueens(5))    {    for(String s : ss)    System.out.println(s);    System.out.println();    }    }       public List<String[]> solveNQueens(int n) {        List<String[]> ll = new LinkedList<String[]>();        char[][][] charsOnStep = new char[n+1][n][n];        charsOnStep[0] = this.getChars(n);        int pre = -1;//上一步是第几步                Stack<int[]> steps = new Stack<int[]>();//用行,列值对来表示步骤        steps.push(new int[]{0,0});        pre = -1;        charsOnStep[1] = this.putQ(0, 0, charsOnStep[0]);        while(!steps.isEmpty())        {        int[] head = steps.peek();        int r,c;        if(pre >= head[1])//回溯        {        r = head[0]+1;//回溯时,要接着上次访问的行数+1的位置        c = head[1];        steps.pop();        }        else        {        r = 0;        c = head[1]+1;        }        int i =c;        for(;i<n; i++)//列        {        boolean found = false;        pre = i;                    for(int j = r;j<n; j++)//行                    {                        char[][] temp = charsOnStep[i];                        if(temp[j][i] == '#')                        {                        charsOnStep[i+1] = putQ(j,i,temp);                        steps.push(new int[]{j,i});                        found = true;                        r = 0;//这里需要把r重置为0,使下一列继续从0开始扫描                        break;                        }                                            }                    if(!found)//没找到,说明走到i列时不能走下去了,需要回溯                    {                    break;                    }                            }        if(i == n)//已经走到最后了,记录结果,然后该回溯了        {        pre = i;        ll.add(ctoss(charsOnStep[n]));        }                }                return ll;            }        //用一个二维的字符数组构造字符串数组    private String[] ctoss(char[][] cs)    {    String[] re = new String[cs.length];    for(int i = 0;i<cs.length; i++)    re[i] = new String(cs[i]);    return re;    }    //在r行c列上放置Q,并依据此Q的位置更新其直线斜线上的点为'.'    public char[][] putQ(int r, int c, char[][] cs)    {    cs = copy(cs);        cs[r][c] = 'Q';        for(int i = 0;i<cs.length; i++)            if(i != r)                cs[i][c] = '.';        for(int i = 1;i < cs.length-c;i++)        {            cs[r][c+i] = '.';            if(r+i < cs.length)                cs[r+i][c+i] = '.';            if(r-i >= 0)                cs[r-i][c+i] = '.';        }        return cs;    }        public char[][] copy(char[][] cs)    {        char[][] c = new char[cs.length][cs.length];        for(int i = 0;i<cs.length; i++)            for(int j = 0;j<cs.length; j++)                c[i][j] = cs[i][j];        return c;    }        //初始化一个字符的二维数组,初始值用#标记    public char[][] getChars(int n)    {        char[][] cs = new char[n][n];        for(int i = 0;i<n; i++)            for(int j = 0;j<n; j++)                cs[i][j] = INIT;        return cs;    }}




0 0
原创粉丝点击