zoukankan      html  css  js  c++  java
  • N皇后问题




    /**
    * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
    */

    N皇后第一版代码:性能较差,但是完全由自己写粗来的,基于此版本优化:

    package com.javartisan.redpacket;
    
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    /**
     * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
     */
    class Solution {
    
        public static List<List<String>> solveNQueens(int n) {
    
            List<List<String>> ans = new ArrayList<>();
            byte[][] mtx = new byte[n][n];
            ArrayList<String> an = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                an.add("");
            }
            trace(ans, an, n, n, mtx);
            HashSet<List<String>> set = new HashSet<>(ans);
            return new ArrayList<>(set);
        }
    
        public static void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx) {
    
            if (cur == 0) {
                ans.add((List<String>) an.clone());
                return;
            }
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (check(mtx, i, j, n)) {
                        mtx[i][j] = 1;
                        StringBuilder sb = new StringBuilder();
                        for (int k = 0; k < n; k++) {
                            if (k == j) {
                                sb.append("Q");
                            } else {
                                sb.append(".");
                            }
                        }
                        an.set(i, sb.toString());
                        trace(ans, an, n, --cur, mtx);
                        an.set(i, "");
                        mtx[i][j] = 0;
                        cur++;
                    }
                }
            }
    
        }
    
    
        public static boolean check(byte[][] mtx, int x, int y, int n) {
    
            boolean status = true;
    
            for (int i = 0; i < n && status; i++) {
                if (mtx[x][i] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = 0; i < n && status; i++) {
                if (mtx[i][y] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i > 0 && j > 0 && status; i--, j--) {
                if (mtx[i - 1][j - 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j < n - 1 && status; i++, j++) {
    
                if (mtx[i + 1][j + 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j > 0 && status; i++, j--) {
    
                if (mtx[i + 1][j - 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i > 0 && j < n - 1 && status; i--, j++) {
    
                if (mtx[i - 1][j + 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            return status;
        }
    
        public static void main(String[] args) {
    
            byte[][] mtx = {
                    {0, 0, 1, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
            };
    
            int n =7;
            long start = System.currentTimeMillis();
            System.out.println(solveNQueens(n));
            System.out.println(System.currentTimeMillis() - start);
            System.out.println(solveNQueens(n).size());
    
        }
    }

    简单优化版:

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    /**
     * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
     */
    class Solution {
    
    
        public static List<List<String>> solveNQueens(int n) {
    
            byte[] x = new byte[n];
            byte[] y = new byte[n];
    
            List<List<String>> ans = new ArrayList<>();
            byte[][] mtx = new byte[n][n];
            ArrayList<String> an = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                an.add("");
            }
            trace(ans, an, n, n, mtx, x, y);
            HashSet<List<String>> set = new HashSet<>(ans);
            return new ArrayList<>(set);
        }
    
        public static void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx, byte[] usedX, byte[] usedY) {
    
            if (cur == 0) {
                ans.add((List<String>) an.clone());
                return;
            }
            for (int i = 0; i < n; i++) {
                if (usedX[i] == 1) {
                    continue;
                }
                for (int j = 0; j < n; j++) {
                    if (usedY[j] != 1 && check(mtx, i, j, n)) {
                        mtx[i][j] = 1;
                        usedX[i] = 1;
                        usedY[j] = 1;
                        StringBuilder sb = new StringBuilder();
                        for (int k = 0; k < n; k++) {
                            if (k == j) {
                                sb.append("Q");
                            } else {
                                sb.append(".");
                            }
                        }
                        an.set(i, sb.toString());
                        trace(ans, an, n, --cur, mtx, usedX, usedY);
                        an.set(i, "");
                        mtx[i][j] = 0;
                        usedX[i] = 0;
                        usedY[j] = 0;
                        cur++;
                    }
                }
            }
    
        }
    
    
        public static boolean check(byte[][] mtx, int x, int y, int n) {
    
            boolean status = true;
    
            for (int i = 0; i < n && status; i++) {
                if (mtx[x][i] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = 0; i < n && status; i++) {
                if (mtx[i][y] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i > 0 && j > 0 && status; i--, j--) {
                if (mtx[i - 1][j - 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j < n - 1 && status; i++, j++) {
    
                if (mtx[i + 1][j + 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j > 0 && status; i++, j--) {
    
                if (mtx[i + 1][j - 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            for (int i = x, j = y; i > 0 && j < n - 1 && status; i--, j++) {
    
                if (mtx[i - 1][j + 1] == 1) {
                    status = false;
                    break;
                }
            }
    
            return status;
        }
    
        public static void main(String[] args) {
    
            byte[][] mtx = {
                    {0, 0, 1, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
            };
    
            System.out.println(solveNQueens(4).size());
    
    
            int n = 7;
            long start = System.currentTimeMillis();
            System.out.println(solveNQueens(n));
            System.out.println(System.currentTimeMillis() - start);
            start = System.currentTimeMillis();
            System.out.println(solveNQueens(8).size());
            System.out.println(System.currentTimeMillis() - start);
        }
    }
    

      

    优化第三版:

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    /**
     * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
     */
    class Solution {
    
        StringBuilder sb = null;
        byte[] mx = null;
        byte[] my = null;
    
        public List<List<String>> solveNQueens(int n) {
    
            List<List<String>> ans = new ArrayList<>(n);
            byte[][] mtx = new byte[n][n];
            ArrayList<String> an = new ArrayList<>(n);
            sb=new StringBuilder(n);
            for (int i = 0; i < n; i++) {
                an.add("");
                sb.append(".");
            }
            mx = new byte[n];
            my = new byte[n];
            trace(ans, an, n, n, mtx, 0);
            return ans;
        }
    
        public void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx, int x) {
    
            if (cur == 0) {
                ans.add((List<String>) an.clone());
                return;
            }
            for (int i = x; i < n; i++) {
                if (mx[i] == 1) {
                    continue;
                }
                for (int j = 0; j < n; j++) {
                    if (my[j] != 1 && check(mtx, i, j, n)) {
                        mtx[i][j] = 1;
                        mx[i] = 1;
                        my[j] = 1;
                        StringBuilder builder = new StringBuilder(this.sb);
                        builder.setCharAt(j, 'Q');
                        an.set(i, builder.toString());
                        trace(ans, an, n, --cur, mtx, i+1);
                        an.set(i, "");
                        mtx[i][j] = 0;
                        mx[i] = 0;
                        my[j] = 0;
                        cur++;
                    }
                }
            }
    
        }
    
        public boolean check(byte[][] mtx, int x, int y, int n) {
    
            for (int i = 0; i < n; i++) {
                if (mtx[x][i] == 1) {
                    return false;
                }
            }
    
            for (int i = 0; i < n; i++) {
                if (mtx[i][y] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i > 0 && j > 0; i--, j--) {
                if (mtx[i - 1][j - 1] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j < n - 1; i++, j++) {
    
                if (mtx[i + 1][j + 1] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j > 0; i++, j--) {
    
                if (mtx[i + 1][j - 1] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i > 0 && j < n - 1; i--, j++) {
    
                if (mtx[i - 1][j + 1] == 1) {
                    return false;
                }
            }
    
            return true;
        }
    
        public static void main(String[] args) {
    
            byte[][] mtx = {
                    {0, 0, 1, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
            };
    
            //  System.out.println(check(mtx, 1, 3, 4));
    //
    //        for (int i = 0; i < 4; i++) {
    //            for (int j = 0; j < 4; j++) {
    //                System.out.println("i = " + i + " j = " + j + "   " + check(mtx, i, j, 4));
    //            }
    //        }
    
              System.out.println(new Solution().solveNQueens(4));
    
        }
    }
    

      

      

    不超时可以通过了。

    优化第4版本,对于当前i,j判断当前行与列是否允许放皇后通过mx,my 单个坐标进行判断,而不是使用二维矩阵:

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    /**
     * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
     */
    class Solution {
    
        StringBuilder sb = null;
        byte[] mx = null;
        byte[] my = null;
    
        public List<List<String>> solveNQueens(int n) {
    
            List<List<String>> ans = new ArrayList<>(n);
            byte[][] mtx = new byte[n][n];
            ArrayList<String> an = new ArrayList<>(n);
            sb=new StringBuilder(n);
            for (int i = 0; i < n; i++) {
                an.add("");
                sb.append(".");
            }
            mx = new byte[n];
            my = new byte[n];
            trace(ans, an, n, n, mtx, 0);
            return ans;
        }
    
        public void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx, int x) {
    
            if (cur == 0) {
                ans.add((List<String>) an.clone());
                return;
            }
            for (int i = x; i < n; i++) {
                if (mx[i] == 1) {
                    continue;
                }
                for (int j = 0; j < n; j++) {
                    if (my[j] != 1 && check(mtx, i, j, n)) {
                        mtx[i][j] = 1;
                        mx[i] = 1;
                        my[j] = 1;
                        StringBuilder builder = new StringBuilder(this.sb);
                        builder.setCharAt(j, 'Q');
                        an.set(i, builder.toString());
                        trace(ans, an, n, --cur, mtx, i+1);
                        an.set(i, "");
                        mtx[i][j] = 0;
                        mx[i] = 0;
                        my[j] = 0;
                        cur++;
                    }
                }
            }
    
        }
    
        public boolean check(byte[][] mtx, int x, int y, int n) {
            /*
            for (int i = 0; i < n; i++) {
                if (mtx[x][i] == 1) {
                    return false;
                }
            }
    
            for (int i = 0; i < n; i++) {
                if (mtx[i][y] == 1) {
                    return false;
                }
            }
            */
            for (int i = x, j = y; i > 0 && j > 0; i--, j--) {
                if (mtx[i - 1][j - 1] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j < n - 1; i++, j++) {
    
                if (mtx[i + 1][j + 1] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i < n - 1 && j > 0; i++, j--) {
    
                if (mtx[i + 1][j - 1] == 1) {
                    return false;
                }
            }
    
            for (int i = x, j = y; i > 0 && j < n - 1; i--, j++) {
    
                if (mtx[i - 1][j + 1] == 1) {
                    return false;
                }
            }
    
            return true;
        }
    
        public static void main(String[] args) {
    
            byte[][] mtx = {
                    {0, 0, 1, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
            };
    
            //  System.out.println(check(mtx, 1, 3, 4));
    //
    //        for (int i = 0; i < 4; i++) {
    //            for (int j = 0; j < 4; j++) {
    //                System.out.println("i = " + i + " j = " + j + "   " + check(mtx, i, j, 4));
    //            }
    //        }
    
              System.out.println(new Solution().solveNQueens(4));
    
        }
    }
    

      

  • 相关阅读:
    2013-11-26的工作-【工作日志】
    grails下的httpclient
    如何解决grails2.3.2中不能运行fork模式
    华丽的bootstrap3碰到土鳖IE6
    grails中报Cannot create a session after the response has been committed异常的解决办法
    听自己喜欢的文章-【睿读】
    动态规划----完全背包问题
    动态规划----最长公共子序列(LCS)问题
    动态规划----数字三角形问题
    动态规划----钢条切割问题
  • 原文地址:https://www.cnblogs.com/leodaxin/p/11267341.html
Copyright © 2011-2022 走看看