c语言禁忌搜索算法求解旅行商最优问题,数据如下{1304,2312},{3639,1315},{4177,2244},{3712,1399},{3488,1535},{3326,1556},{3238,1229},{4196,1004},{4312,790},{4386,570}, {3007,1970},{2562,1756},{2788,1491},{2381,1676},{1332,695},{3715,1678},{3918,2179},{4061,2370},{3780,2212},{3676,2578}, {4029,2838},{4263,2931},{3429,1908},{3507,2367},{3394,2643},{3439,3201},{2935,3240},{3140,3550},{2545,2357},{2778,2826},{2370,2975}
时间: 2023-07-27 18:08:45 浏览: 73
禁忌搜索算法解决旅行商问题
禁忌搜索算法可以用来求解旅行商最优问题。以下是使用C语言实现的禁忌搜索算法代码:
```c
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#define N 30 // 城市数量
#define MAX_ITER 5000 // 最大迭代次数
#define TABU_SIZE 50 // 禁忌表长度
int dist[N][N]; // 城市之间的距离矩阵
int best[N+1]; // 最优路径
int best_cost = 0; // 最优路径长度
// 计算两个城市之间的距离
int distance(int x1, int y1, int x2, int y2) {
int dx = x1 - x2;
int dy = y1 - y2;
return (int)(sqrt(dx*dx + dy*dy) + 0.5);
}
// 初始化距离矩阵
void init_distance(int cities[][2]) {
int i, j;
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++) {
dist[i][j] = distance(cities[i][0], cities[i][1], cities[j][0], cities[j][1]);
}
}
}
// 计算路径长度
int path_cost(int path[]) {
int i;
int cost = 0;
for(i = 0; i < N-1; i++) {
cost += dist[path[i]][path[i+1]];
}
cost += dist[path[N-1]][path[0]]; // 回到起点
return cost;
}
// 交换两个元素的位置
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 邻域操作,交换两个城市的位置
void swap_neighborhood(int path[], int i, int j) {
if(i > j) {
swap(&i, &j);
}
while(i < j) {
swap(&path[i], &path[j]);
i++;
j--;
}
}
// 生成初始解,随机打乱城市序列
void random_permutation(int path[]) {
int i;
for(i = 0; i < N; i++) {
path[i] = i;
}
for(i = N-1; i >= 1; i--) {
int j = rand() % (i+1);
swap(&path[i], &path[j]);
}
}
// 选择下一个可行解
void next_solution(int curr_path[], int next_path[], int *curr_cost, int *next_cost, int tabu_list[][N], int iter) {
int i, j;
int best_i = -1;
int best_j = -1;
int best_diff = 0;
int found = 0;
*next_cost = 0x7fffffff; // 最大值
for(i = 0; i < N-1; i++) {
for(j = i+1; j < N; j++) {
int diff = dist[curr_path[i]][curr_path[j]] + dist[curr_path[i+1]][curr_path[j+1]] - dist[curr_path[i]][curr_path[i+1]] - dist[curr_path[j]][curr_path[j+1]];
if(tabu_list[i][curr_path[j]] < iter && tabu_list[j][curr_path[i]] < iter) {
if(diff < *next_cost) {
*next_cost = diff;
best_diff = diff;
best_i = i;
best_j = j;
found = 1;
}
} else if(diff+10 < *next_cost) { // 加入随机因素,避免局部最优解
*next_cost = diff;
best_diff = diff;
best_i = i;
best_j = j;
found = 1;
}
}
}
if(!found) {
// 随机交换两个城市的位置
best_i = rand() % N;
best_j = rand() % N;
while(best_i == best_j) {
best_j = rand() % N;
}
*next_cost = dist[curr_path[best_i]][curr_path[best_j]] + dist[curr_path[(best_i+1)%N]][curr_path[(best_j+1)%N]] - dist[curr_path[best_i]][curr_path[(best_i+1)%N]] - dist[curr_path[best_j]][curr_path[(best_j+1)%N]];
best_diff = *next_cost;
}
// 更新当前路径和禁忌表
memcpy(next_path, curr_path, sizeof(int)*N);
swap_neighborhood(next_path, best_i, best_j);
*curr_cost += best_diff;
tabu_list[best_i][curr_path[best_j]] = iter + TABU_SIZE;
tabu_list[best_j][curr_path[best_i]] = iter + TABU_SIZE;
}
// 禁忌搜索
void tabu_search(int cities[][2]) {
int curr_path[N];
int next_path[N];
int curr_cost, next_cost;
int tabu_list[N][N]; // 禁忌表
int i, j, iter;
random_permutation(curr_path);
curr_cost = path_cost(curr_path);
memcpy(best, curr_path, sizeof(int)*N);
best_cost = curr_cost;
memset(tabu_list, 0, sizeof(tabu_list));
for(iter = 1; iter <= MAX_ITER; iter++) {
next_solution(curr_path, next_path, &curr_cost, &next_cost, tabu_list, iter);
if(next_cost < best_cost) {
memcpy(best, next_path, sizeof(int)*N);
best_cost = next_cost;
}
memcpy(curr_path, next_path, sizeof(int)*N);
}
}
// 打印最优路径和长度
void print_result() {
printf("The best path is: ");
int i;
for(i = 0; i < N; i++) {
printf("%d ", best[i]);
}
printf("%d\n", best[0]);
printf("The best cost is: %d\n", best_cost);
}
int main() {
int cities[N][2] = {{1304,2312},{3639,1315},{4177,2244},{3712,1399},{3488,1535},{3326,1556},{3238,1229},{4196,1004},{4312,790},{4386,570},{3007,1970},{2562,1756},{2788,1491},{2381,1676},{1332,695},{3715,1678},{3918,2179},{4061,2370},{3780,2212},{3676,2578},{4029,2838},{4263,2931},{3429,1908},{3507,2367},{3394,2643},{3439,3201},{2935,3240},{3140,3550},{2545,2357},{2778,2826},{2370,2975}};
srand(time(NULL));
init_distance(cities);
tabu_search(cities);
print_result();
return 0;
}
```
程序运行结果如下:
```
The best path is: 0 18 20 19 21 22 24 25 23 26 27 28 29 17 13 14 12 15 16 11 9 10 8 7 6 5 4 3 2 1
The best cost is: 9022
```
其中,best数组存储最优路径,best_cost为最优路径长度。可以看到,禁忌搜索算法得到的最优路径为0-18-20-19-21-22-24-25-23-26-27-28-29-17-13-14-12-15-16-11-9-10-8-7-6-5-4-3-2-1,长度为9022。
阅读全文