【发布时间】:2013-12-23 08:20:44
【问题描述】:
我正在编写一个数独求解算法,并且我正在尝试实现一种演绎方法来解决这个难题。但是我必须对递归或其他东西有一个松散的把握,因为我的算法似乎最多只改变一次电路板,即使我设置的条件应该在大多数情况下返回 true。这是我的方法
public void CRME() {
for (Node n : cells) {
scanColumn(n);
scanRow(n);
scanMiniGrid(n);
sortBoardVals();
}
}
这会扫描每一列、每一行和每一个小网格,并在代表棋盘的数组列表中剔除每个节点的可能值。
public void solve(){
boolean canChange = false;
ArrayList<Node> before = new ArrayList<Node>(cells);
CRME();
for(Node n : cells){
int i = cells.indexOf(n);
if(n.isEqual(before.get(i))){
canChange = false;
} else {
canChange = true;
break;
}
}
if(canChange){
System.out.println("Solving...");
solve();
}
}
这是一个求解算法,它应该自我调用,直到它完全耗尽。
这是我的节点类
public class Node {
public ArrayList<Integer> posVals = new ArrayList<Integer>(9) {{
add(1);
add(2);
add(3);
add(4);
add(5);
add(6);
add(7);
add(8);
add(9);
}};
private int ROW_ID;
private int COL_ID;
private int MG_ID;
static boolean hasChanged = true;
int value = 0;
public boolean isEqual(Node n){
if(this.posVals.size() == n.posVals.size()){
return true;
}
else return false;
}
}
我可能正在考虑重新考虑我的项目,因为我认为使用数组列表会使问题复杂化。
CRME 中的方法基本上是扫描每个节点并找到包含在相同 Column Row 和 MiniGrid 中的每个节点的值,并将它们从节点的可能值数组列表中删除。
排序板值方法然后检查节点中的数组列表的大小是否为 1,如果是,则将该节点的值设置为 Arraylist 中的最后一个值。
public void sortBoardVals() {
for (Node n : cells) {
if (n.posVals.size() == 1) {
if (n.value == 0)
n.value = n.posVals.get(0);
}
}
}
public void scanColumn(Node n) {
for (Node node : cells) {
ArrayList<Integer> toRemove = new ArrayList<Integer>();
if (node.get_COL_ID() == n.get_COL_ID()) {
toRemove.add(node.getValue());
}
n.posVals.removeAll(toRemove);
}
}
public void scanRow(Node n) {
for (Node node : cells) {
ArrayList<Integer> toRemove = new ArrayList<Integer>();
if (node.get_ROW_ID() == n.get_ROW_ID()) {
toRemove.add(node.getValue());
}
n.posVals.removeAll(toRemove);
}
}
public void scanMiniGrid(Node n) {
for (Node node : cells) {
ArrayList<Integer> toRemove = new ArrayList<Integer>();
if (node.get_MG_ID() == n.get_MG_ID()) {
toRemove.add(node.getValue());
}
n.posVals.removeAll(toRemove);
}
}
【问题讨论】:
-
因为节点数是恒定的,所以应该使用 Node[] 而不是 ArrayList
。同样,您应该使用 boolean[] 而不是 ArrayList 来表示可能的值(对于每个值,true = 可能,false = 不可能) -
没想到那样,看来我得彻底重新考虑数据结构了,谢谢。
-
@Saposhiente 那是非常小的东西。我看不出这些更改中的任何一个会如何使这变得更容易。
-
@JohnKugelman 这不是一个解决方案,但它可以提高效率。这就是为什么我将其发布为评论,而不是答案。
标签: java recursion methods arraylist sudoku