Я использую язык 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();
}
}
}
И это часть вывода:
Странный вывод
Любые подробные ответы будут оценены.
Я проверял много раз и до сих пор ничего не получил. Надеюсь найти где ошибка.
Похоже, что для каждой итерации i во вложенном цикле в getNextState есть значительная вероятность того, что будет вызван оператор nextState[i] = currentState[i];
,
он вызывается по крайней мере один раз для каждого i, что приводит к полному переопределению nextState на currentState к концу цикла.
Вот почему, похоже, ничего не изменилось.
Похоже, что ваш
#getNextState
потенциально решает проблему напрямую, а не просто делает один шаг (обратите внимание, что напечатанное «следующее состояние» каждый раз является полным решением, и только первый Q слева неуместен). Было бы полезно включить ваши начальные состояния, возможно, с конфигурацией, которая находится в 1-2 шагах от решения (чтобы вы знали ожидаемые шаги). Это также помогло бы объяснить части вашего кода (например, какint[] state
представляет собой массив индексов строк для каждой королевы, поэтомуstate[4] == 1
означает, что королева в 1-индексированном 5-м столбце находится во 2-й строке).