N-queens问题和Backtracking~如何表示节点?

时间:2010-03-16 03:12:59

标签: java

我正在尝试构建一个库来解决不同的约束问题。 我首先尝试了4皇后问题,我无法弄清楚我如何能代表节点。 我的意思是我可以在没有任何树类(通过维数组)的情况下完成它,但我想将其表示为树结构问题。

树的深度总是<= 4

这是我的代码:

class Node {
  Node []next ;
  int value;
  int depth;
  String name;
  Node(){
      next=null;
      value=0;
      depth=0;
      name=null;
  }
  Node(int value,int depth,String name){
      this.value=value;
      //this.next=child;
      this.depth=depth;
      this.name=name;
  }

class Tree{ Node root; Stack stack; String[] vars={"Q1","Q2","Q3","Q4"}; int[] domain={1,2,3,4}; int count=0; Tree(){ root=new Node(); stack=new Stack();

}

void start(){ stack.push(root); count++; search(stack.pop(),0); }

boolean consistent(Node current){ boolean flag=true; int n=current.getDepth(); //need more return flag; }

private void search(Node current,int num) { if(num==3&&consistent(current)){ System.out.println("solution !"); num=0; } else{ if(consistent(current)){ Node child[]=new Node[4]; for(int i=0;i<4;i++) child[i]=new Node(domain[i],current.getDepth()+1,vars[num]); current.setNext(child); for(int i=3;i>=0;i--) stack.push(child[i]); search(stack.pop(),num+1); } search(stack.pop(),num); } }<code>

3 个答案:

答案 0 :(得分:6)

有很多方法可以解决N皇后问题。你提到了回溯,所以我将解释用这种技术解决它的最佳方法之一。

首先,请注意,同一列中不能有两个皇后:每列必须只有一个皇后,不多也不少。因此,不是将女王位置表示为二维(r, c),而是将一个女王准确地分配给一列; q[c] == r表示分配到c列的女王位于r行。

现在你的问题变得更加简单了:现在可以保证不会有两个皇后在同一列上。你现在只需要强制执行其他2个约束:同一行上没有两个皇后,同一对角线上没有两个皇后。

检查两个皇后是否在同一行上是微不足道的:q[c1] == q[c2]表示两个皇后在同一行。但请注意,您实际上并不需要比较每对皇后的q值:您可以简单地为每一行分配一个标签,当您在该行上放置一个女王时,您可以标记该行作为“使用”。没有其他女王可以放在已使用的行上。

检查两个皇后是否在同一对角线上并不困难:根据q[c1]q[c2]找到方程式。您可以像对行一样标记对角线。

所以问题现在只是找到[1..N]的排列,这些排列可以分配给满足所有3个约束的q[1..N]。我会把剩下的留给你。

答案 1 :(得分:1)

任何时间点问题的状态是棋盘上每列中每个皇后的位置。正如@poly所说,两个皇后不可能在同一列中。 @poly在解释问题的参数方面做得很好。

如果您采取回溯方法,那么您要做的就是为第一位女王选择一个位置,然后继续观察它是否有效。接下来,您选择第二位女王的位置,然后是第三位,最后是第四位。如果第4个不起作用,你将回溯到第三个,如果第三个不起作用,你将回到第二个,等等。

我将在4x4主板上谈论4皇后案例。我认为它的方式是树的根是你做出零选择的地方。根下面的第一层将是四个孩子......第一列中第一个女王的每个可能位置的一个孩子(1,2,3和4)。在树的第二高处,您可以在第二列中选择第二个女王的位置,依此类推。

这是一个部分完成的树:

                          ""
                            |
              -----------------------------------------------
              1                  2            3             4
              |                  |            |             |        
     ---------------------
     1,1   1,2   1,3   1,4
            |
------------------------------------

1,1,1     1,1,2     1,1,3      1,1,4

                                 |
        -------------------------------------------------
        1,1,4,1      1,1,4,2       1,1,4,3        1,1,4,4

所以树的所有叶子都是形式(A,B,C,D)的元组,其中A是第一个女王的位置,B是第二个的位置,C是第三个的位置, D是第四个位置。

所以我会说每个节点的“价值”是你到目前为止所做的选择。我认为我不认为它是int。您可以将其保留为string,如果您愿意或类似ArrayList之类的内容可能会使您的递归更容易一些。希望有所帮助。

答案 2 :(得分:0)

你把它倒了 - 你应该存储节点的父节点而不是子节点。