模拟退火求解TSP问题
模拟退火算法步骤
1.寻找下一个解
2.计算下一个解的能量
3.决定是否接受这个解
4.降温
算法模板
double randfloat() {
return rand()/(RAND_MAX+0.0);
}
double T0 = 1000000,Tk = 1,T = T0,d = 0.9999;
int x = initx();//当前解(初始解)
int ansE,nowE;//全局最优解的能量,当前解的能量
ansE = nowE = E(x);
while(T > Tk) {
//1.产生新解
int newx = generate(x);
//2.计算新解的能量
int newE = E(newx);
//3.确定是否接受
if(newE < nowE || randfloat() > exp((nowE-newE)/T)){
nowE = newE;
x = newx;
}
//4.降温
T *= d;
//5.更新全局最优解
Optimize(ansE,newE);
}
TSP问题代码
交题链接
http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=1420
#include <iostream>
#include <algorithm>
#include <cstring>
#include <ctime>
#include <cmath>
#include <assert.h>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define int long long
int G[21][21];
int n,m;
int run(int x[]){
int ans = 0;
rep(i,1,n) {
ans += G[x[i-1]][x[i%n]];
}
return ans;
}
double randfloat() {
return rand()/(RAND_MAX+0.0);
}
int solve() {
srand(time(NULL));
int x[22];
rep(i,0,n-1) x[i] = i+1;
double T0 = 100000000,Tk = 1,T = T0,d = 0.99;
int ans = run(x);
int preans = ans;
while(T > Tk) {
//1.产生新解
int a = rand()%n;
int b = rand()%n;
//std::swap(x[a],x[b]);
std::reverse(x+a,x+b+1);
//2.计算下一个解的能量
int newans = run(x);
Min(ans,newans);
//3.确定是否接受
if(newans >= preans) {
if(randfloat() > exp((preans-newans)/T))
//std::swap(x[a],x[b]);
std::reverse(x+a,x+b+1);
else preans = newans;
}
else preans = newans;
//4.降温
T *= d;
}
return ans;
}
signed main() {
std::cin >> n >> m;
//setinf(G);
if(n == 1) return 0*puts("0");
rep(i,1,n) rep(j,1,n) {
G[i][j] = 1e11;
}
rep(i,1,m) {
int a,b,c;
std::cin >> a >> b >> c;
Min(G[a][b],c);
Min(G[b][a],c);
}
std::cout << solve() << std::endl;
}