tsp动态规划非递归写法c++

看注释

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using namespace std;

#define N 4
#define MAX 0x3f3f3f3f
int dp[N][1 << (N - 1)];   // dp数组
int path[N][1 << (N - 1)]; // 路径
//  课本例题 N=4
int distances[N][N] = {{MAX, 3, 6, 7},
                       {5, MAX, 2, 3},
                       {6, 4, MAX, 2},
                       {3, 7, 5, MAX}}; // 距离
int removeCity(int j, int k)
{ // 从j二进制表示的城市集合中去除k号城市(k位设为0)
    return j - (1 << (k - 1));
}

int TSP()
{
    if (N == 1)
        return 0; // 只有一个结点

    for (int i = 1; i < N; i++)
    {
        dp[i][0] = distances[i][0]; // 初始化所有城市到0号城市的距离
    }

    for (int j = 1; j < (1 << (N - 1)); j++)//集合<j> -> 0
    {

        for (int i = 1; i < N; i++)
        {
            if ((j >> (i - 1)) % 2 == 0)
            { // i号城市不在j二进制形式表示的城市集合里
                // cout << "i " << i << "j " << j << endl;
                int min = MAX;
                int next_city = i;
                for (int k = 1; k < N; k++)
                {
                    if ((j >> (k - 1)) % 2 != 0)
                    {                                                         // k号城市在j二进制形式表示的城市集合里
                        int temp = distances[i][k] + dp[k][removeCity(j, k)]; // 表示把k号城市从j城市集合中去除
                        if (temp < min)
                        {
                            min = temp;
                            next_city = k;
                        }
                    }
                }
                dp[i][j] = min;
                path[i][j] = next_city;
            }
        }
    }

    //{0,<S>},0经过<j>到0
    int min = MAX;
    int next_city = 0;
    int j = (1 << (N - 1)) - 1; // 代表除0号城市外的所有城市组成的集合
    for (int k = 1; k < N; k++)
    {
        int temp = distances[0][k] + dp[k][removeCity(j, k)];
        if (temp < min)
        {
            min = temp;
            next_city = k;
        }
    }
    dp[0][j] = min;
    path[0][j] = next_city;

    return dp[0][j];
}

void printPath(int i, int j)
{ // 打印路线 i为出发城市编号 j为剩下城市组成的集合
    if (j != 0)
    {
        cout << i << " -> ";
        int next_city = path[i][j];
        printPath(next_city, removeCity(j, next_city));
    }
    else
    {
        cout << i << " -> " << 0;
    }
}

int main()
{

    // 纵轴为0,1,2...表示城市编号
    // 横轴为000,001,010,...第x位为1,代表该集合里面有x号城市

    // 随机初始化distances[N][N]
    // srand((unsigned int)time(NULL));
    // for (int i = 0; i < N; i++)
    // {
    //     for (int j = i; j < N; j++)
    //     {
    //         if (i == j)
    //             distances[i][j] = MAX;
    //         else
    //         {
    //             int temp = rand();
    //             while (temp == 0)
    //             {
    //                 temp = rand();
    //             }
    //             distances[i][j] = distances[j][i] = temp;
    //         }
    //     }
    // }

    // 打印代价矩阵
    cout << "结点数为:[" << N << "]" << endl;
    cout << "代价矩阵为:" << endl;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (distances[i][j] == MAX)
                cout << setw(5) << "INF"
                     << " ";
            else
                cout << setw(5) << distances[i][j] << " ";
        }
        cout << endl;
    }

    cout << "最短距离为:" << TSP() << endl;
    cout << "旅行路线为:";
    printPath(0, (1 << (N - 1)) - 1);
    system("pause");
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只川页

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值