TSP问题:模拟退火算法

/* 利用模拟退火算法求解TSP问题 */
#include"iostream"
#include"ctime"
#include"cmath"

#define MAX 10000
#define INF 10000000
#define E 0.000000001  // 迭代误差   
#define L 20000    // 迭代次数   
#define AT 0.999   // 降温系数   
#define T 1       // 初始温度   
using namespace std;

struct element {     //用来排序的数据结构
    int data;  // 数据
    int index;  // 序号
};

int tsp(int d[][MAX], int n, double e, int l, double at, double t, int s0[]);  //利用模拟退火算法求解最短路径
int cmp(const void *a, const void *b); //升序排列
void rand_of_n(int a[], int n);  //产生 1-n 的随机排列并存到 a[] 中
int random(int m, int n);

int dis[MAX][MAX];   // dis[i][j] 表示地点i到地点j的距离,0 表示自身点

int main() {
    int i, j;
    int n = 100;  // 点的个数
    for (i = 0; i < n; i++)     // 随机产生距离 1-100
        for (j = i; j < n; j++)
            if (i == j)
                dis[i][j] = 0;
            else
                dis[i][j] = dis[j][i] = random(1, 100);
    FILE *fp = fopen("data.txt", "w");  // 将距离存入文件中
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++)
            fprintf(fp, "%d ", dis[i][j]);
        fprintf(fp, "\n");
    }
    fclose(fp);
    int sum, sum0, s0[MAX];
    sum0 = 0;   //顺序遍历时的路程
    for (i = 0; i < n - 1; i++)
        sum0 = sum0 + dis[i][i + 1];
    sum0 = sum0 + dis[n - 1][0];
    sum = tsp(dis, n, E, L, AT, T, s0);
    cout << "The total distance of the sequential access: " << sum0 << "\tOptimized total distance: " << sum << endl;
    cout << "Best Path: ";
    for (i = 1; i <= n; i++)
        printf("%d-", s0[i]);
    printf("%d\n", s0[1]);
    return 0;
}

int cmp(const void *a, const void *b) {   // 升序排序
    return ((struct element *) a)->data - ((struct element *) b)->data;
}

void rand_of_n(int a[], int n) {
    int i;
    struct element ele[MAX];
    srand((int) time(0));  // 初始化随机数种子
    for (i = 0; i < n; i++) {
        ele[i].data = rand();  // 随机生成一个数
        ele[i].index = i + 1;
    }
    qsort(ele, n, sizeof(ele[0]), cmp);  //排序
    for (i = 0; i < n; i++) {
        a[i] = ele[i].index;
    }
}

int random(int m, int n) {   //产生m-n的随机数
    int a;
    double x = (double) rand() / RAND_MAX;
    a = (int) (x * (n - m) + 0.5) + m;
    return a;
}

int tsp(int d[][MAX], int n, double e, int l, double at, double t, int s0[]) {
    int i, j, s[MAX], sum, temp;
    sum = INF;
    for (i = 0; i < 1000; i++) {  //利用蒙特卡洛方法产生初始解
        rand_of_n(&s[1], n);
        s[0] = 0;
        s[n + 1] = 0;  //第一个和最后一个点为起始点
        temp = 0;
        for (j = 0; j <= n; j++)
            temp = temp + d[s[j]][s[j + 1]];
        if (temp < sum) {
            for (j = 0; j <= n + 1; j++)
                s0[j] = s[j];
            sum = temp;
        }
    }
    for (i = 0; i < l; i++) {    //退火过程
        int c1, c2;
        c1 = random(1, n);
        c2 = random(1, n);
        if (c1 > c2) {
            int temp = c2;
            c2 = c1;
            c1 = temp;
        }
        if (c1 == c2)
            continue;
        int df = d[s0[c1 - 1]][s0[c2]] + d[s0[c1]][s0[c2 + 1]] - d[s0[c1 - 1]][s0[c1]] -
                 d[s0[c2]][s0[c2 + 1]]; //计算代价函数
        if (df < 0) {  //接受准则
            while (c1 < c2) {
                int temp = s0[c2];
                s0[c2] = s0[c1];
                s0[c1] = temp;
                c1++;
                c2--;
            }
            sum = sum + df;
        } else if (exp(-df / t) > ((double) rand() / RAND_MAX)) {
            while (c1 < c2) {
                int temp = s0[c2];
                s0[c2] = s0[c1];
                s0[c1] = temp;
                c1++;
                c2--;
            }
            sum = sum + df;
        }
        t = t * at;
        if (t < e)
            break;
    }
    return sum;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值