2014-11-08 23 views
0

我在框架中使用回溯来处理带约束修剪的图着色问题。图形的每个可能的状态(即,可以放在图上的颜色的每个组合)由状态对象表示。该框架要求每个国家生产所有的孩子,选择最合适的孩子,并重复寻找最佳解决方案,并沿途修剪。我碰到的麻烦是这样的:状态对象在生成新对象时覆盖以前的孩子

当我在一个状态下调用nextChild()时,它将由该状态产生的前一个孩子改变为刚刚产生的状态。

以下是我认为是我的代码的相关部分:

public State nextChild() { 
//  System.out.println("currentColor: "+ colors.get(currentColor) + " firstUncolored " + this.firstUncolored); 
//  previous line for debugging 
     GraphColoringState child = childSetup(); 
     child.gcolors[firstUncolored] = colors.get(currentColor++); 
     if(this.currentColor == colors.size()){ 
      this.currentColor = 0; 
      this.hasMoreChildren = false; 
     } 
     return child; 
    } 

private GraphColoringState childSetup() { 
     GraphColoringState theClone = new GraphColoringState(graph, colors); 
     theClone.gcolors = this.gcolors; 
     theClone.firstUncolored = this.firstUncolored +1; 
     theClone.currentColor = 0; 
     return theClone; 
    } 

当我制作和打印的孩子是这样的:

State s = new GraphColoringState(graph, colors); 
System.out.println(s); 

State s1 = s.nextChild(); 
System.out.println(s1); 

State s2 = s.nextChild(); 
System.out.println(s2); 

State s3 = s.nextChild(); 
System.out.println(s3);  

我得到这样的输出:

, , , , , , 
Red, , , , , , 
Green, , , , , , 
Blue, , , , , , 

但是当我生产和打印这种方式:

System.out.println(s); 

State s1 = s.nextChild(); 
State s2 = s.nextChild(); 
State s3 = s.nextChild(); 

System.out.println(s1); 
System.out.println(s2); 
System.out.println(s3); 

我得到这个不幸的输出:

, , , , , , 
Blue, , , , , , 
Blue, , , , , , 
Blue, , , , , , 

我说这个输出是不幸的,因为为了使回溯框架的工作,我需要所有这些孩子的存储在同一时间,不同的值。我曾尝试在每个州内使用数组实例变量来存储它的子项,但无济于事。

为什么我的代码改变了我已经生成的孩子的值?

请谢谢! :)

回答

0

gcolors是你设置为新的子值

theClone.gcolors = this.gcolors; 

然后修改gcolors在nextChild()数组

child.gcolors[firstUncolored] = colors.get(currentColor++); 

为了避免这样的错误,你可以使用一个改为不可修改的列表。

+0

我不知道我明白 - 我应该让gcolors变量最终?由于我的代码试图修改它,是不是只是抛出异常? – 2014-11-08 19:45:56

+0

如果你想保留年龄较大的孩子,那么你不能覆盖他们的状态。你可以使GraphColoringState不变,方法是使所有变量都是最终的,并用列表替换gcolors数组。通过调用Collections.unmodifiableList(..)将列表包装到一个不可修改的列表中,确保该列表也是不可变的。这样,你不可能意外地改变前一个孩子的状态。但是,原来的错误似乎是你复制gcolors数组然后修改它。 – avidD 2014-11-08 19:56:34

+0

我明白了。 那么,我找到了一个解决方案 - 我只是改变了行 theClone.gcolors = this.gcolors; 阅读 theClone.gcolors = this.gcolors.clone(); 真的非常简单,我可能不需要打扰你们都与它。 谢谢你的建议,祝你有美好的一天! – 2014-11-08 20:35:48

0

原来,问题是在这个行:

theClone.gcolors = this.gcolors; 

这导致所有国家的共享一个阵列表示每个节点的颜色。我真正想要的是每个国家拥有自己的阵列。

更改该行:

theClone.gcolors = this.gcolors.clone(); 

是需要所有。感谢大家的帮助!