找出给定某些条件的2D布尔数组的所有可能组合(使用Java)

时间:2014-08-27 00:39:27

标签: java

假设有一个2d布尔数组

boolean[][] = {  x  x  x  x  x  x  x
                 x  x  x  x  x  x  x
                 x  x  x  x  x  x  x
                 x  x  x  x  x  x  x  }

标准:

  1. 每列必须有2个'true'
  2. 每行不能超过4个'true'
  3. 例如,解决方案可以是:

    boolean[][] = {  T  T  T  T  F  F  F
                     T  T  T  T  F  F  F
                     F  F  F  F  T  T  T
                     F  F  F  F  T  T  T  }
    

    另一个:

    boolean[][] = {  T  F  T  F  F  T  T
                     F  T  T  T  F  F  F
                     F  F  F  T  T  T  F
                     T  T  F  F  T  F  T  }
    

    如果根据上述两个标准编写递归函数以找出所有可能的组合?

    我希望我可以展示我尝试的东西,但我甚至不知道如何开始。我试图通过使用面向对象的方式,通过为行或列创建类来解决这个问题,但似乎没有帮助简化它,因为行和列彼此密切相关。

    提前致谢!

1 个答案:

答案 0 :(得分:1)

static final int NB_ROWS = 4;
static final int NB_COLUMNS = 7;

public static void main(String[] args) {

    boolean[][] initialState = new boolean[NB_ROWS][NB_COLUMNS];
    //everything is initialize to false
    System.out.println(algo(initialState, 0, 0, 0));

}

//path: column by column
public static int algo(boolean[][] state, int currentRow, int currentColumn, int acc) {
    if(currentColumn == NB_COLUMNS) { //end of the array reached
        return acc + 1;
    }
    if(currentRow == NB_ROWS) { //end of the column reached
        if(checkColumn(state, currentColumn)) { //the current column meets requirements
            return algo(state, 0, currentColumn+1, acc);
        } else {
            return acc;
        }
    }
    state[currentRow][currentColumn] = true; //try with true at the given coordinates
    if(checkRow(state, currentRow)) { //current row meets the requirements
        acc += algo(state, currentRow+1, currentColumn, 0); //start with a fresh counter
    }
    state[currentRow][currentColumn] = false; //try with false at the given coordinates
    // no need to check row with a false value
    return algo(state, currentRow+1, currentColumn, acc);
}

public static boolean checkColumn(boolean[][] state, int currentColumn) {
    int count = 0;
    for(int i=0; i<NB_ROWS; i++) {
        if(state[i][currentColumn])
            count++;
    }
    return count == 2;
}

public static boolean checkRow(boolean[][] state, int currentRow) {
    int count = 0;
    for(int i=0; i<NB_COLUMNS; i++) {
        if(state[currentRow][i])
            count++;
    }
    return count <= 5;
}

我在代码中加了一些注释来解释我在做什么,但用英文单词。

在递归调用的任何给定点:尝试将T放入单元格(p,q)。如果它没有中断行条件,则在单元格(p + 1,q)上调用算法。之后,在两种情况下,将F放入单元格(p,q)并在单元格上调用算法(p + 1,q)。

在单元格(p,q)上调用算法时,首先检查坐标是否在数组内。如果p大于行号,请检查是否满足列条件,并在单元格(0,q + 1)上调用算法。如果q大于列号,则到达数组的末尾,然后返回累加器(&#34;获胜&#34;已找到的情况)+ 1。

测试了3行和4列,它返回81 = 3 * 3 * 3 * 3,这确实是一个好结果(每列有3种可能,自4&lt; 5以来没有行约束)。