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

时间:2018-12-03 07:51:46

标签: java recursion

我正在尝试编写一个功能,该功能获得MxN尺寸的板子,并在其中放置一列和一列,其中放置一个女王。然后我想看看那个女王是否受到威胁。 通常,我会将该行并检查是否有其他皇后区,对于列和对角线也使用for循环进行检查。 但是这里稍有变化,即使在同一行中还有另外一堵墙,木板上的墙壁也可以使皇后区安全:

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

其中Q是皇后,X是墙,*是空瓷砖。 即使排在第二位的女王也不会受到威胁。

整个板子也保存在一个2d数组中,其中为Queens赋予int值为1,墙为-1,空白为0。

我的想法是遍历整行,如果某个地方有皇后,那么我应该寻找一堵墙,从该位置一直到我要看的皇后,再铺一层for环。但是在我的女王之后还有第二部分。

我尝试过考虑求和,但这也不是很有效。 有人对如何实现这一点有任何想法吗? (如果受到威胁,则返回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

我用'标记了我的女王,即使该示例为true,我的代码也将返回false。然后,我必须对角线和列做同样的操作。帮助。

2 个答案:

答案 0 :(得分:1)

这是与Iterator s合作的绝佳机会。

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() {
                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()) {
        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)的女王/王后在(2,4)受到女王的威胁。

答案 1 :(得分:0)

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

  1. 如果您碰到另一个女王,则将受到威胁,请返回var result = data2.GroupBy(n => new { n.Name, n.Date}) .Select(cl => new Result { Name = cl.First().Name, Date = cl.First().Date, Hours = cl.Sum(c => c.Hour), }).ToList();
  2. 如果碰到墙壁,您将朝那个方向安全,请继续进行下一个检查。
  3. 如果您击中棋盘的边缘,则在该方向上是安全的,请继续进行下一个检查。


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; } 来发现撞墙的威胁,但是TBH,我认为代码看起来会更糟:

boolean