Метаэвристический алгоритм для решения задач оптимизации
import random
import math
def ok(A):
z = 0
for i in range(n):
for j in range(i + 1, n):
if abs(i - j) == abs(A[i] - A[j]):
z += 1
return z
n = int(input())
t = 10000.0
A = list(range(1, n + 1))
random.shuffle(A)
ans = ok(A)
C = list(A)
z = ans
while z > 0:
i = random.randint(0, n - 1)
j = random.randint(0, n - 1)
if i == j:
continue
A[i], A[j] = A[j], A[i]
val = ok(A)
if val < ans or random.random() < math.exp((ans - val) / t):
ans = val
if val == 0:
C = list(A)
z = val
break
else:
A[i], A[j] = A[j], A[i]
t *= 0.99
print(*C)
#include <bits/stdc++.h>
using namespace std;
int ok(const vector<int>& A, int n) {
int z = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (abs(i - j) == abs(A[i] - A[j])) {
z++;
}
}
}
return z;
}
int main() {
srand(time(0));
int n;
cin >> n;
double t = 10000.0;
vector<int> A(n);
for (int i = 0; i < n; ++i) {
A[i] = i + 1;
}
random_shuffle(A.begin(), A.end());
int ans = ok(A, n);
vector<int> C = A;
int z = ans;
while (z > 0) {
int i = rand() % n;
int j = rand() % n;
if (i == j) continue;
swap(A[i], A[j]);
int val = ok(A, n);
double random_value = (double)rand() / RAND_MAX;
if (val < ans || random_value < exp((ans - val) / t)) {
ans = val;
if (val == 0) {
C = A;
z = val;
break;
}
} else {
swap(A[i], A[j]);
}
t *= 0.99;
}
for (int num : C) {
cout << num << " ";
}
cout << endl;
return 0;
}
Имитация отжига (Simulated Annealing) — это вероятностный алгоритм глобальной оптимизации, вдохновлённый процессом отжига в металлургии. Он позволяет находить приближённые решения сложных задач оптимизации.
В отличие от жадных алгоритмов, которые могут застрять в локальном минимуме, имитация отжига с некоторой вероятностью принимает ухудшающие решения, что позволяет "выпрыгнуть" из локальных оптимумов и найти глобальный минимум.
Новое решение принимается, если:
В данной реализации алгоритм ищет расстановку n ферзей на доске n×n так, чтобы они не атаковали друг друга. Оптимальное решение — когда количество конфликтующих пар равно 0.
Временная сложность: зависит от количества итераций (обычно O(n² × итераций)).
Ввод:
n — размер доски и количество ферзейВывод:
8
Вывод (пример): 5 1 8 4 2 7 3 6
Это одна из возможных расстановок 8 ферзей, где никакие два не атакуют друг друга.
Примечание: алгоритм вероятностный, поэтому при разных запусках могут получаться разные решения. Для n=8 решение всегда существует.
Введите количество ферзей (размер доски):