Java Неожиданный результат

Я использую язык java для написания алгоритма восхождения на холм для решения проблемы восьми ферзей. Приведенный выше код определяет класс HillClimbing, который содержит основной метод и несколько вспомогательных методов. Метод main сначала использует метод generateRandomState для создания случайного состояния, а затем использует метод getHeuristic для вычисления значения эвристической функции состояния. Далее программа входит в цикл, непрерывно использует метод getNextState для получения следующего состояния и обновляет значение эвристической функции до тех пор, пока значение эвристической функции не станет равным 0.

Метод generateRandomState использует класс Java Random для генерации случайного массива длины N, представляющего строку, в которой находится ферзь каждого столбца на шахматной доске. Метод getHeuristic вычисляет значение эвристической функции для заданного состояния, т.е. сколько пар ферзей атакуют друг друга на доске. Метод getNextState получает следующее состояние на основе текущего состояния, он обходит ферзей каждого столбца на доске, и пытается переместить их на другие строки, если после перемещения значение эвристической функции становится меньше, то обновить состояние.

Во время выполнения существует бесконечный цикл. Когда я проверил код, я обнаружил, что функция getNextState каждый раз успешно обновляла bestHeuristic, но nextState не обновлялся. Я не знаю, где проблема. Вопрос о связи между ссылками и памятью в java? Вот мой код. (Извините за длинное описание, но я просто хочу сделать все ясно)

import java.util.Random;

public class HillClimbing {
    private static final int N = 8;
    private static final Random RANDOM = new Random();

    public static void main(String[] args) {
        int[] state = generateRandomState();
        int heuristic = getHeuristic(state);
        System.out.println("This is initial state:");
        printState(state);

        while (heuristic != 0) {
            state = getNextState(state);
            heuristic = getHeuristic(state);
        }

        printState(state);
    }

    private static int[] generateRandomState() {
        int[] state = new int[N];
        for (int i = 0; i < N; i++) {
            state[i] = RANDOM.nextInt(N);
        }
        return state;
    }

    private static int getHeuristic(int[] state) {
        int heuristic = 0;
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                if (state[i] == state[j] || Math.abs(state[i] - state[j]) == Math.abs(i - j)) {
                    heuristic++;
                }
            }
        }
        return heuristic;
    }

    private static int[] getNextState(int[] currentState) {
        int[] nextState = new int[N];
        int currentHeuristic = getHeuristic(currentState);
        int bestHeuristic = currentHeuristic;
        boolean found = false;

        for (int i = 0; i < N; i++) {
            nextState[i] = currentState[i];
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (currentState[i] == j) continue;

                nextState[i] = j;
                int nextHeuristic = getHeuristic(nextState);

                if (nextHeuristic < bestHeuristic) {
                    System.out.println("heuristic after movement: "+ nextHeuristic);
                    bestHeuristic = nextHeuristic;
                    found = true;
                } else {
                    nextState[i] = currentState[i];
                }
            }
        }

        if (!found) {
            return getNextState(generateRandomState());
        }
        
        System.out.println("The next state:");
        printState(nextState);
        return nextState;
    }

    private static void printState(int[] state) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (state[j] == i) {
                    System.out.print("Q ");
                } else {
                    System.out.print(". ");
                }
            }
            System.out.println();
        }
    }
}

И это часть вывода: Странный вывод
Любые подробные ответы будут оценены.

Я проверял много раз и до сих пор ничего не получил. Надеюсь найти где ошибка.

Похоже, что ваш #getNextState потенциально решает проблему напрямую, а не просто делает один шаг (обратите внимание, что напечатанное «следующее состояние» каждый раз является полным решением, и только первый Q слева неуместен). Было бы полезно включить ваши начальные состояния, возможно, с конфигурацией, которая находится в 1-2 шагах от решения (чтобы вы знали ожидаемые шаги). Это также помогло бы объяснить части вашего кода (например, как int[] state представляет собой массив индексов строк для каждой королевы, поэтому state[4] == 1 означает, что королева в 1-индексированном 5-м столбце находится во 2-й строке).

Rogue 19.04.2023 16:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, что для каждой итерации i во вложенном цикле в getNextState есть значительная вероятность того, что будет вызван оператор nextState[i] = currentState[i];, он вызывается по крайней мере один раз для каждого i, что приводит к полному переопределению nextState на currentState к концу цикла. Вот почему, похоже, ничего не изменилось.

Другие вопросы по теме