对于n组城市坐标,寻找最短路径使其经过所有城市并回到起点。
1 37 52
2 49 49
3 52 64
4 20 26
5 40 30
6 21 47
7 17 63
8 31 62
9 52 33
10 51 21
11 42 41
12 31 32
13 5 25
14 12 42
15 36 16
16 52 41
17 27 23
18 17 33
19 13 13
20 57 58
21 62 42
22 42 57
23 16 57
24 8 52
25 7 38
26 27 68
27 30 48
28 43 67
29 58 48
30 58 27
31 37 69
32 38 46
33 46 10
34 61 33
35 62 63
36 63 69
37 32 22
38 45 35
39 59 15
40 5 6
41 10 17
42 21 10
43 5 64
44 30 15
45 39 10
46 32 39
47 25 32
48 25 55
49 48 28
50 56 37
51 30 40
最优解:426
1、设置初始温度,随机初始化一个初始解;2、开始进入外循环体
2.a进入内循环体
2.a.a 根据一定规则,在现有解的基础上生成一个新解;
2.a.b记录内循环的最优解
2.a.c退出内循环
2.b 按照一定规则,判断是否接受新解,即使用新解替换旧解;
2.c温度下降
3、退出外循环
1、设置初始温度,随机初始化一个初始解;2、开始进入外循环体
2.a进入内循环体
2.a.a 在现有解即城市访问序列中,随机交换一组或多组城市的顺序,以生成一个新解;
2.a.b记录内循环的最优解
2.a.c退出内循环(终止条件我用的是迭代次数k)
2.b 按照metropolis准则,根据新解的能量值(new_energy)、旧解的能量值(new_energy)和当前温度 t 判断是否接受新解,即使用新解替换旧解;
2.c温度下降(我设置的是接受新状态,温度下降的会快些,不接受会慢些降温)
3、退出外循环(终止条件是温度降低到一定程度)
【注】metropolis准则
P= P = {1,newenergylessthenoldenergy;exp(−Δt),newenergymorethenoldenergy; { 1 , n e w e n e r g y l e s s t h e n o l d e n e r g y ; exp ( − Δ t ) , n e w e n e r g y m o r e t h e n o l d e n e r g y ;
Δ Δ 指新旧解的能量差,是个正数
P P 指接受新解的概率
初始温度 tempterature = 1000;
成功降温因子 u = 0.998;
失败降温因子 v = 0.999;
内循环迭代次数 k = 100;
#include
#include
#include
#include
#include
using namespace std;
const int num = 1000;//city number
const int width = 100;
const int height = 100;
typedef struct node {
int x;
int y;
}city;
city citys[num];//citys
double dic[num][num];//distance from two citys;
bool visit[num];//visited
int N;//real citys
int seq[num];//最优路径序列
double answer;//最优路径长度
const int tempterature = 1000;//初始温度
const double u = 0.998;//成功降温因子
const double v = 0.999;//失败降温因子
int k = 100;//对每个温度迭代次数
void init() {//set N&&x-y
N = 51;
citys[0].x = 37; citys[0].y = 52;
citys[1].x = 49; citys[1].y = 49;
citys[2].x = 52; citys[2].y = 64;
citys[3].x = 20; citys[3].y = 26;
citys[4].x = 40; citys[4].y = 30;
citys[5].x = 21; citys[5].y = 47;
citys[6].x = 17; citys[6].y = 63;
citys[7].x = 31; citys[7].y = 62;
citys[8].x = 52; citys[8].y = 33;
citys[9].x = 51; citys[9].y = 21;
citys[10].x = 42; citys[10].y = 41;
citys[11].x = 31; citys[11].y = 32;
citys[12].x = 5; citys[12].y = 25;
citys[13].x = 12; citys[13].y = 42;
citys[14].x = 36; citys[14].y = 16;
citys[15].x = 52; citys[15].y = 41;
citys[16].x = 27; citys[16].y = 23;
citys[17].x = 17; citys[17].y = 33;
citys[18].x = 13; citys[18].y = 13;
citys[19].x = 57; citys[19].y = 58;
citys[20].x = 62; citys[20].y = 42;
citys[21].x = 42; citys[21].y = 57;
citys[22].x = 16; citys[22].y = 57;
citys[23].x = 8; citys[23].y = 52;
citys[24].x = 7; citys[24].y = 38;
citys[25].x = 27; citys[25].y = 68;
citys[26].x = 30; citys[26].y = 48;
citys[27].x = 43; citys[27].y = 67;
citys[28].x = 58; citys[28].y = 48;
citys[29].x = 58; citys[29].y = 27;
citys[30].x = 37; citys[30].y = 69;
citys[31].x = 38; citys[31].y = 46;
citys[32].x = 46; citys[32].y = 10;
citys[33].x = 61; citys[33].y = 33;
citys[34].x = 62; citys[34].y = 63;
citys[35].x = 63; citys[35].y = 69;
citys[36].x = 32; citys[36].y = 22;
citys[37].x = 45; citys[37].y = 35;
citys[38].x = 59; citys[38].y = 15;
citys[39].x = 5; citys[39].y = 6;
citys[40].x = 10; citys[40].y = 17;
citys[41].x = 21; citys[41].y = 10;
citys[42].x = 5; citys[42].y = 64;
citys[43].x = 30; citys[43].y = 15;
citys[44].x = 39; citys[44].y = 10;
citys[45].x = 32; citys[45].y = 39;
citys[46].x = 25; citys[46].y = 32;
citys[47].x = 25; citys[47].y = 55;
citys[48].x = 48; citys[48].y = 28;
citys[49].x = 56; citys[49].y = 37;
citys[50].x = 30; citys[50].y = 40;
}
void set_dic() {//set distance
for (int i = 0; ifor (int j = 0; jsqrt(pow(citys[i].x - citys[j].x, 2) + pow(citys[i].y - citys[j].y, 2));
}
}
}
double dic_two_point(city a, city b) {
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
double count_energy(int* conf) {
double temp = 0;
for (int i = 1; i1]]);
}
temp += dic_two_point(citys[conf[0]], citys[conf[N - 1]]);
return temp;
}
bool metro(double f1, double f2, double t) {
if (f2 < f1)
return true;
//else
// return false;
double p = exp(-(f2 - f1) / t);
int bignum = 1e9;
if (rand() % bignumreturn true;
return false;
}
void generate(int* s) {//随机产生一组新解
bool v[num];
memset(v, false, sizeof(v));
for (int i = 0; iwhile (v[s[i]]) {
s[i] = rand() % N;
}
v[s[i]] = true;
}
}
void generate1(int* s) {//随机交换序列中的一组城市顺序
int ti = rand() % N;
int tj = ti;
while (ti == tj)
tj = rand() % N;
for (int i = 0; ivoid generate2(int* s) {//随机交换序列中的两组城市顺序
int ti = rand() % N;
int tj = ti;
int tk = ti;
while (ti == tj)
tj = rand() % N;
while (ti == tj || tj == tk || ti == tk)
tk = rand() % N;
for (int i = 0; ivoid generate3(int* s) {//随机选序列中的三个城市互相交换顺序
int ti = rand() % N;
int tj = ti;
int tm = rand() % N;
int tn = ti;
while (ti == tj)
tj = rand() % N;
while (tm == tn)
tn = rand() % N;
for (int i = 0; ivoid generate0(int* s) {//以上三种交换方式等概率选择
int temp = rand() % 3;
if (temp == 0)
generate1(s);
else if (temp == 1)
generate2(s);
else if (temp == 2)
generate3(s);
}
void moni() {
double t = tempterature;
int seq_t[num];
for (int i = 0; i//初始化当前序列
seq[i] = seq_t[i] = i;
}
double new_energy = 1, old_energy = 0;
while (t>1e-9&&fabs(new_energy - old_energy)>1e-9) {//温度作为控制变量
int t_k = k;
int seq_tt[num];
while (t_k--&&fabs(new_energy - old_energy)>1e-9) {//迭代次数作为控制变量
generate1(seq_tt);
new_energy = count_energy(seq_tt);//new
old_energy = count_energy(seq_t);//old
if (metro(old_energy, new_energy, t))
for (int i = 0; i < N; ++i)
seq_t[i] = seq_tt[i];
}
new_energy = count_energy(seq_t);//new
old_energy = answer;//old
if (metro(old_energy, new_energy, t)) {
for (int i = 0; i < N; ++i)
seq[i] = seq_t[i];
answer = count_energy(seq);
t *= u;//接受新状态降温因子0.98
}
else
t *= v;//不接受新状态降温因子0.99
}
answer = count_energy(seq);
}
void output() {
cout << "the best road is : \n";
for (int i = 0; i < N; ++i) {
cout << seq[i];
if (i == N - 1)
cout << endl;
else
cout << " -> ";
}
cout << "the length of the road is " << answer << endl;
}
void test() {
ifstream ifile("data.txt");
if (!ifile) {
cout << "open field\n";
return;
}
while (!ifile.eof()) {
int te = 0;
ifile >> te;
ifile >> citys[te - 1].x >> citys[te - 1].y;
}
}
int main() {
srand(time(nullptr));
int t;
while (cin >> t) {//仅作为重启算法开关使用,无意义
init();//使用程序内置数据使用init()函数,
//test();//使用文件读取数据使用test()函数,
set_dic();//计算每个城市之间的距离
moni();//退火
output();//输出
}
return 0;
}