我有一个单线程数独求解器,我想使用多线程。我计划将N个线程委托给板上的每个阵列。每个线程将返回他们在每个单元格中找到的可能性的数量,并从那里我们测试这些值并在必要时回溯。
我坚持的是一旦线程在板上插入一个可能的值,如何保持一致,因为它改变了其他线程中的可能性。
我正在使用一种名为最受约束的变量的启发式算法。在每个步骤中,我们计算每个单元格中的可能性数量,并尝试在该单元格中找到具有最小可能的候选项以最小化冲突的值。例如:
1 2 0 0
0 0 0 0
0 0 0 0
0 0 3 4
第1行第3列具有最少的候选者(1),并且只有4个可以放在那里。这是算法的核心,也是我想要使用多线程并行化的内容。
这是我用来解决数独谜题的课程:
public class LogicalSolver
{
private int numberOfSteps;
public LogicalSolver()
{
numberOfSteps = 0;
}
public boolean runLogicSolver(SudokuBoard board)
{
return logicalSolver(board);
}
private boolean logicalSolver(SudokuBoard board)
{
boolean solved = false;
int row = -1;
int column = -1;
int candidates[] = new int[board.GRIDSIZE];
int numOfCandidates = 0;
for (int currentRow = 0; currentRow < board.GRIDSIZE; currentRow++)
{
for (int currentColumn = 0; currentColumn < board.GRIDSIZE; currentColumn++)
{
if (board.getValue(currentRow, currentColumn) == 0)
{
int newCandidates[] = getCandidates(board, currentRow, currentColumn);
int numOfNewCandidates = getNumOfNewCandidates(newCandidates);
if (row < 0 || numOfNewCandidates < numOfCandidates)
{
row = currentRow;
column = currentColumn;
candidates = newCandidates;
numOfCandidates = numOfNewCandidates;
}
}
}
}
if (row < 0)
{
solved = true;
}
else
{
for (int i = 0; i < candidates.length && candidates[i] != 0; i++)
{
board.setValue(row, column, candidates[i]);
numberOfSteps++;
if (logicalSolver(board))
{
solved = true;
break;
}
board.setValue(row, column, 0);
}
}
return solved;
}
private int[] getCandidates(SudokuBoard board, int row, int column)
{
int newCandidates[] = new int[board.GRIDSIZE];
int index = 0;
for (int value = 1; value <= board.GRIDSIZE; value++)
{
boolean collision = false;
for (int offset = 0; offset < board.GRIDSIZE; offset++)
{
int rowSubGrid = (row - row % board.ROWS) + (offset / board.ROWS);
int columnSubGrid = (column - column % board.COLUMNS) + (offset % board.COLUMNS);
if (board.getValue(row, offset) == value || board.getValue(offset, column) == value
|| board.getValue(rowSubGrid, columnSubGrid) == value)
{
collision = true;
break;
}
}
if (!collision)
{
newCandidates[index] = value;
index++;
}
}
return newCandidates;
}
private int getNumOfNewCandidates(int newCandidates[])
{
int numOfNewCandidates = 0;
for (int i = 0; i < newCandidates.length && newCandidates[i] != 0; i++)
{
numOfNewCandidates++;
}
return numOfNewCandidates;
}
public void displayNumberOfSteps()
{
System.out.println("It took " + numberOfSteps + " steps to solve this puzzle. \n");
}
}
答案 0 :(得分:0)
我认为这是使用ForkJoinTask和ForkJoinPool的绝佳场所。
在前往解决方案的每一步中,您都会创建一个新的ForkJoinTask来探索每个可能的下一步。
每个任务都有自己正在研究的状态的副本,因此在设置单元格时无需同步。而是设置单元格会产生一个新的ForkJoinTask来探索设置该单元格的后果。
如果你必须同步,那么你将失去多线程的一些好处。