Я написал алгоритм обратного отслеживания для генерации судокуса с произвольным размером. Моя проблема заключается в изменении скорости алгоритма генерации.Скорость генерации Судоку
Я добавил несколько консольных выходов, чтобы увидеть результаты. Я создал ~ 20 Sudokus размером 16x16, каждый из которых имел время генерации от 1 мс до 150 мс. Следующее заняло 10 минут, и это даже не закончилось. (Я остановил программу). Учитывая это, я думаю, что я ошибся в реализации backtracking, которая препятствует продвижению алгоритма.
Вот код:
public class Generator {
public static NormalSudoku generateNormal(int size) {
NormalSudoku ns = new NormalSudoku(size);
boolean[][][] track = new boolean[size][size][size];
ArrayList<Integer> vals = new ArrayList<Integer>();
fill(vals, size);
int row = 0;
int col = 0;
int val = 0;
int count = 0;
while (row < size) {
boolean found = false;
while (!vals.isEmpty() && !found) {
val = vals.get((int) (Math.random() * vals.size()));
track[row][col][val - 1] = true;
if (ns.checkValue(row, col, val)) {
ns.setValue(row, col, val);
fill(vals, size);
col++;
found = true;
} else {
vals.remove(Integer.valueOf(val));
}
if (col >= size) {
row++;
col = 0;
}
}
if (vals.isEmpty()) {
ns.setValue(row, col, 0);
for (int i = 0; i < size; i++) {
track[row][col][i] = false;
}
col--;
if (col < 0) {
row--;
col = size - 1;
}
ns.setValue(row, col, 0);
fill(vals, track, row, col);
}
}
return ns;
}
private static void fill(ArrayList<Integer> vals, int size) {
vals.clear();
for (int i = 1; i <= size; i++) {
vals.add(i);
}
}
private static void fill(ArrayList<Integer> vals, boolean[][][] track,
int row, int col) {
vals.clear();
for (int i = 0; i < track[row][col].length; i++) {
if (!track[row][col][i]) {
vals.add(Integer.valueOf(i + 1));
}
}
}
}
Объяснение кода:
логический [] [] [] трек:
своего рода контрольный список для значений, которые уже пробовали (чтобы уменьшить накладные расходы при попытке повторить одно и то же случайное значение несколько раз). Я положил трек [row] [col] [val] в true, если я уже попытался поместить val в это поле. Если я вернусь, я должен очистить метки для этой ячейки, чтобы снова сделать значения.
ns.checkValue:
Устанавливает значение в ячейке, проверяет, является ли судоку по-прежнему верна, устанавливает старое значение снова и возвращает истина/ложь.
ns.setValue:
Просто устанавливает значение в ячейке.
Vals:
список массив, содержащий значения, которые еще не пробовали для этой ячейки. Если я продвигаюсь вперед, список, очевидно, должен содержать все возможные числа. Если я вернусь, список должен содержать только числа, которые еще не были проверены. (Я использую массив треков, чтобы понять это).
Что я делаю неправильно?
Greets
Возможно, вы захотите опубликовать это на [codereview] (http://codereview.stackexchange.com/). –
Я также пробовал сделать предварительно заполненную программу судоку в мои ранние дни программирования, сначала вам нужно проанализировать все возможные правила для полностью заполненной судоку, вы обнаружите, что одного обратного отслеживания в одиночку не хватит, и именно поэтому иногда программа никогда я тоже столкнулся с такими же ситуациями ... –