Когда требуется рекурсивное обратное отслеживание?

Я делаю SudokuSolver для класса, и у меня возникают проблемы с методом решения. Мое текущее решение использует рекурсивный обратный отсчет (я думаю).

Требования к присваиванию

int solve() - пытается решить головоломку, используя описанную выше стратегию. Возвращает количество решений.

(Стратегия, описанная выше)

При назначении номера пятну никогда не присваивайте номер, который в данный момент конфликтует с точечной строкой, столбцом или квадратом. Мы внимательно следим за назначением юридических чисел на место, вместо того, чтобы назначать любое число 1..9 и находить проблему позже в рекурсии. Предположим, что начальная сетка является законной и после этого совершает только юридические назначения.

Идея псевдокода

Я могу следовать этому итеративно для небольшого ввода. Например, скажу, что у меня есть нерешенные ячейки Cell # 1 и Cell # 2. # 1 имеет возможности {1, 3} и # 2 имеет возможности {2, 3}. Я бы тогда

set 1 to 1
    set 2 to 2
        hasConflicts? 0 : 1
    set 2 to 3
        hasConflicts? 0 : 1
set 1 to 3
    set 2 to 2
        hasConflicts? 0 : 1
    set 2 to 3
        hasConflicts? 0 : 1

Фактический код

public int solve() {
    long startTime = System.currentTimeMillis();
    int result = 0;

    if (!hasConflicts()) {
        Queue<VariableCell> unsolved = getUnsolved();
        reduceUnsolvedPossibilities(unsolved);  // Gets the possibilities down from all of 1-9

        if (!hasConflicts()) {
            result = solveRec(unsolved);
        }
    }

    mElapsedTime = System.currentTimeMillis() - startTime;
    return result;
}

protected int solveRec(Queue<VariableCell> unsolved) {
    if (unsolved.isEmpty()) {
        return (hasConflicts()) ? 0 : 1;
    }

    int result = 0;
    VariableCell cell = unsolved.remove();
    Iterator<String> possibilityIt = cell.getPossibilities().iterator();

    while (possibilityIt.hasNext()) {
        cell.setSymbol(possibilityIt.next());

        if (hasConflicts()) {
            possibilityIt.remove();
        } else {
            ++result;
        }
    }

    return result + solveRec(unsolved);
}

Результаты тестирования

testSolveSingleSolution
    expected 1, actual 1

testSolveSolved
    expected 1, actual 1

testSolveUnsolvable
    expected 0, actual 0

testSolveMultiSolutions
    expected 2, actual 7  // MAJOR PROBLEM!

Некоторые хорошие пояснения рекурсивного обратного отсчета

Вопрос

Я уже делал рекурсивный backtracking, я просмотрел все эти ссылки выше и более, и у меня все еще есть проблемы. Я думаю, что проблема заключается в моем размышлении о том, как решить эту проблему. (См. Идея псевдокода.) Уместно ли использовать рекурсивный откат для исчерпывающего поиска? Верно ли возвращение, но реализация неправильная? Есть ли лучший алгоритм, который я могу использовать, чем рекурсивный откат?

Ответ 1

Это выглядит как проблема реализации. Проверьте блок, в котором вы увеличиваете результат. Вы действительно хотите увеличивать для каждого действительного значения этой ячейки? И в этом случае перезапишите старшее допустимое значение, если существует несколько допустимых?