首页 文章

验证N皇后问题的解决方案

提问于
浏览
0

我正在尝试编写一个获得MxN尺寸电路板的功能,其中有一列和一行放置一个女王 . 然后我想看看女王是否受到威胁 . 通常我会拿那行检查任何其他皇后,同样的列和对角线使用for循环 . 但是这里有一点点变化,板子上还有墙壁可以保证女王安全,即使同一行中还有另一个:

* * Q X * Q
* * X * * *
* Q X X Q *
Q * X Q Q *

其中Q是女王,X是墙,*是空的瓷砖 . 即使在那一行中有另一个女王,在0,2位置的女王也没有受到威胁 .

整个电路板也保存在一个二维数组中,其中,皇后的int值为1,墙为-1,空白为0 .

我的想法是遍历整行,如果在某个地方有一个女王,那么我应该寻找一个墙,从那个位置到我正在看的女王的另一个循环 . 然而,在我的女王之后还有第二部分 .

我试着考虑总结,但这也不太有用......任何人都有任何关于如何实现这个的想法? (如果受到威胁则返回true;如果没有受到威胁则返回false;)

编辑:这是我的代码

`public static boolean isQueenThreatened(int[][] board, int row, int col){
        boolean safe=true; 
        for(int j = 0; j < col & safe ; j++){
            if(board[row][j]==1) {
                for (int i = j+1 ; i<col ; i++ ) {
                        if(board[row][i]!=-1) safe = false;
                }
            }
        }
        for(int j = col+1; j < board[row].length & safe ; j++){
            if(board[row][j]==1) {
                for (int i = j+1 ; i<board[row].length ; i++ ) {
                    if(board[row][i]!=-1) safe = false;
                }
            }

        }
        return safe;
    }`

所以这个函数得到了女王的位置(假设它是有效的),然后我想翻过那一行,直到我的女王和之后看看是否还有其他的皇后,如果有的话我想检查它们之间是否有任何墙壁为了保护我的女王安全,显然我的工作不起作用,因为如果它们之间除了墙之外什么都没有,它会给出错误,而且只有一面墙就足够了,它不一定都是墙 .

* Q * * X Q' * X Q

我已经用''表示我的女王,我的代码将为该示例返回false,即使它应该是真的..然后我必须对对角线和列做同样的事情......这是我需要帮助的地方 .

2 回答

  • 0

    对于给定的大写位置,您需要遍历行,列和每个对角线 . 在每个方向,您可以遵循相同的规则:

    • 如果你击中另一位女王,你就会受到威胁,返回 true .

    • 如果你碰到一堵墙,你就可以朝这个方向安全,继续进行下一次检查 .

    • 如果你碰到了电路板的边缘,那么你就可以安全地朝那个方向前进,继续进行下一次检查 .

    public static boolean isQueenThreatened(int[][] board, int row, int col) {
        // Go over the row, to the left:
        for (int i = col - 1; i >= 0; --i) {
            int val = board[row][i];
            if (val == 1) {
                return true;
            }
            if (val == -1) {
                break;
            }
        }
    
        // Same logic for:
        // - Going over the row to the right
        // - Going over the column to the top
        // - Going over the column to the bottom
        // - Going over the top left diagonal
        // - Going over the top right diagonal
        // - Going over the bottom left diagonal
        // - Going over the bottom right diagonal
    
        // If you reached here, it means that no early return was performed,
        // and the queen is safe
        return false;
    }
    

    EDIT:

    要回答评论中的要求,您可以添加额外的 boolean 来查找撞墙的威胁,但TBH,我认为代码看起来会更糟糕:

    public static boolean isQueenThreatened(int[][] board, int row, int col) {
        boolean threat = false;
    
        // Go over the row, to the left:
        boolean wall = false;
        for (int i = col - 1; i >= 0 && !threat && !wall; --i) {
            int val = board[row][i];
            if (val == 1) {
                threat = true;
            }
            if (val == -1) {
                wall = true;
            }
        }
    
        // Go over the row, to the right.
        // Reset the wall variable, as you haven't detected a wall in this direction yet
        // The threat potentially found in the previous loop is still present
        // so if it still exists, the loop will be skipped 
        boolean wall = false;
        for (int i = col + 1; i < board[row].length && !threat && !wall; ++i) {
            int val = board[row][i];
            if (val == 1) {
                threat = true;
            }
            if (val == -1) {
                wall = true;
            }
        }
    
        // Same logic for:
        // - Going over the column to the top
        // - Going over the column to the bottom
        // - Going over the top left diagonal
        // - Going over the top right diagonal
        // - Going over the bottom left diagonal
        // - Going over the bottom right diagonal
    
        // If you reached here, it means that no early return was performed,
        // and the queen is safe
        return threat;
    }
    
  • 0

    这是与 Iterator 一起工作的绝佳机会 .

    static class Board {
        private final int width;
        private final int height;
        private final int[][] board;
        private static final int EMPTY = 0;
        private static final int WALL = -1;
        private static final int QUEEN = 1;
    
    
        public Board(int width, int height) {
            this.width = width;
            this.height = height;
            board = new int[height][width];
        }
    
        public Board(String[] setup) {
            this(setup[0].length(), setup.length);
            for (int y = 0; y < setup.length; y++) {
                for (int x = 0; x < setup[y].length(); x++) {
                    switch (setup[y].charAt(x)) {
                        case '*':
                            board[y][x] = EMPTY;
                            break;
                        case 'X':
                            board[y][x] = WALL;
                            break;
                        case 'Q':
                            board[y][x] = QUEEN;
                            break;
                    }
                }
            }
        }
    
        public Iterator<Integer> walk(int xStart, int yStart, int dx, int dy) {
            return new Iterator<Integer>() {
                int x = xStart;
                int y = yStart;
    
                @Override
                public boolean hasNext() {
                    return x + dx < width && y + dy < height
                            && x + dx >= 0 && y + dy >= 0;
                }
    
                @Override
                public Integer next() {
                    //System.out.println("("+(x+dx)+","+(y+dy)+") = "+board[y+dy][x + dx]);
                    return board[y += dy][x += dx];
                }
            };
        }
    
        public int get(int x, int y) {
            return board[y][x];
        }
    }
    
    enum Direction {
        NORTH(0, -1),
        NORTH_WEST(1, -1),
        WEST(1, 0),
        SOUTH_WEST(1, 1),
        SOUTH(0, 1),
        SOUTH_EAST(-1, 1),
        EAST(-1, 0),
        NORTH_EAST(-1, -1),
        ;
        private final int dx;
        private final int dy;
    
        Direction(int dx, int dy) {
            this.dx = dx;
            this.dy = dy;
        }
    }
    
    public static boolean isQueenThreatened(Board board, int row, int col) {
        for (Direction direction : Direction.values()) {
            //System.out.println(direction);
            walk: for (Iterator<Integer> attack = board.walk(col, row, direction.dx, direction.dy); attack.hasNext(); ) {
                switch (attack.next()) {
                    case Board.QUEEN:
                        return true;
                    case Board.WALL:
                        break walk;
                }
            }
        }
        return false;
    }
    
    private void test() {
        String[] test = new String[]{
                "**QX*Q",
                "**X***",
                "*QXXQ*",
                "Q*XQQ*"
        };
        Board board = new Board(test);
        for (int y = 0; y < board.height; y++) {
            for (int x = 0; x < board.width; x++) {
                if (board.get(x, y) == Board.QUEEN) {
                    System.out.println("Queen at position (" + x + "," + y + ") is " + (isQueenThreatened(board, y, x) ? "" : "NOT") + " threatened");
                }
            }
    
        }
    }
    

    顺便说一下 - 你的女王在 (0,2) IS 被女王威胁 (2,4) .

相关问题