首页 > 其他分享 >分支限界法解TSP问题

分支限界法解TSP问题

时间:2023-05-01 21:57:39浏览次数:27  
标签:Node count 限界 int MAX 路径 currentCost TSP 法解

#include<iostream>
#include<queue>
#define INF 1e7
#define MAX 100
using namespace std;

int m[MAX][MAX]; //存储城市间的代价
int bestPath[MAX]; //存储最优路径
int bestCost = 1e7; //存储最小代价
int cityNumber; //城市数目

//排列树的节点定义
struct Node {
    int count; //处理的第几个城市
    int currentCost; //记录目前走过的路径代价之和
    int currentPath[MAX]; //在此节点处的走过的路径记录
    Node() {} //默认构造函数,即普通的定义一个结构体的用法
    Node(int count_, int currentCost_) {
        count = count_;
        currentCost = currentCost_;
        memset(currentPath, 0, sizeof(currentPath));
    }
};

//构建最小堆的比较函数
struct pathCost_cmp {
    bool operator()(Node n1, Node n2){
        return n1.currentCost > n2.currentCost;
    }
};

void branchTSP() {
    //定义最小堆, 即待处理节点的PT表
    priority_queue<Node, vector<Node>, pathCost_cmp> q;
    //初始化一个节点,因为默认从城市1开始探索,所以这个初始化节点的编号是2
    Node initNode(2, 0);
    //初始化解向量(路径记录)
    for (int i = 0; i <= cityNumber; i++) {
        initNode.currentPath[i] = i; //顺序走完所有城市
    }
    q.push(initNode);
    Node currentNode; //每次选择的扩展节点
    while (!q.empty()) {
        // 每次选取堆顶元素作为当前的扩展节点
        currentNode = q.top();
        // 已经选择一次,就从PT表(优先队列中移除),因为不会再选择已经选择过的节点作为扩展节点
        q.pop();
        int c = currentNode.count;//用t记录当前节点是处理的第几个城市
        if (c == cityNumber) {//如果排列树已经来到了第cityNumber层,即叶子节点处
            //检查currentNode是否满足约束条件:1. 从上一个点有办法来到当前节点 2. 当前节点有路回到起点 
            if (m[currentNode.currentPath[c - 1]][currentNode.currentPath[c]] != INF
                && m[currentNode.currentPath[c]][1] != INF) {
                if (currentNode.currentCost + m[currentNode.currentPath[c - 1]][currentNode.currentPath[c]]
                    + m[currentNode.currentPath[c]][1] < bestCost) { //如果当前叶子节点的代价更小,做更新
                    bestCost = currentNode.currentCost + m[currentNode.currentPath[c - 1]][currentNode.currentPath[c]]
                        + m[currentNode.currentPath[c]][1];
                    for (int i = 1; i <= cityNumber; i++) {
                        bestPath[i] = currentNode.currentPath[i]; //更新最优路径为当前叶子节点的currentPath
                    }
                }
            }
            //continue; //既然已经到了叶子节点(无法再扩展),那就进入下一层循环
        }
        else {
            if (currentNode.currentCost <= bestCost) { //现在的代价已经大于最小代价了,没必要做任何处理
                                                       // 如果既不是叶子节点,又没有被剪枝,那么会走到这里
            // 从当前节点开始,搜索下一个可能选取的节点,作为要走往的下一个城市
                for (int i = c; i <= cityNumber; i++) {//如果第j个节点满足约束条件也满足限界条件
                    if (m[currentNode.currentPath[c - 1]][currentNode.currentPath[i]] != INF && currentNode.currentCost
                        + m[currentNode.currentPath[c - 1]][currentNode.currentPath[i]] < bestCost) {
                        Node temp = Node(c + 1, currentNode.currentCost
                            + m[currentNode.currentPath[c - 1]][currentNode.currentPath[i]]); //初始化下一个节点
                        for (int j = 1; j <= cityNumber; j++) {
                            temp.currentPath[j] = currentNode.currentPath[j];
                        }
                        swap(temp.currentPath[c], temp.currentPath[i]); //当前位置c要放第i个城市
                        q.push(temp);
                    }
                }
            }
        }
    }
}

int main() {
    cout << "请输入城市数目" << endl;
    cin >> cityNumber;
    //初始化路径数组,所有的路径代价都是INF
    for (int i = 1; i <= cityNumber; i++) {
        for (int j = 1; j <= cityNumber; j++) {
            m[i][j] = INF;
        }
    }
    memset(bestPath, 0, cityNumber); //初始化bestPath数组
    for (int i = 1; i <= cityNumber; i++) {
        cout << "请输入第" << i << "座城市的路径信息(不通请输入-1)" << endl;
        for (int j = 1; j <= cityNumber; j++) {
            int temp;
            cin >> temp;
            if (temp != -1) {
                m[i][j] = temp;
            }
        }
    }
    branchTSP();
    cout << "最优值为:" << bestCost<<endl;
    cout << "最优解为:" << endl;
    for (int i = 1; i <= cityNumber; i++) {
        cout << bestPath[i] << " ";
    }
    cout << bestPath[1] << endl;
    system("pause");
    return 0;
}

/*输入1:
4
-1 30 6 4
30 -1 5 10
6 5 -1 20
4 10 20 -1
*/

/*输入2:
4
-1 3 6 7
12 -1 2 8
8 6 -1 2
3 7 6 -1
*/

 

标签:Node,count,限界,int,MAX,路径,currentCost,TSP,法解
From: https://www.cnblogs.com/Jocelynn/p/17367054.html

相关文章

  • node.js用ffmpeg切rtsp实时视频流为mp4,并且在网页上播放
    用express.js框架,这部分太简单了,省略npm或者yarn安装fluent-ffmpeg路由部分代码:router.rtspTrackingHandle=function(req,res){logger.info('[tracking]:rtsphandle');leturl=req.query.url||'';//leturl='rtsp://admin:jeewey123@19......
  • python 检查rtsp流是否可用
    importcv2fromfunc_timeoutimportfunc_set_timeout,exceptionsdefcheck_rtsp_stream(url):@func_set_timeout(2)defparse_rtsp_stream(rtsp_address):try:cap=cv2.VideoCapture(rtsp_address)cap.set(cv2.CAP_PRO......
  • 在web端实现rtsp流的视频的播放
    相关了解我们已经知道了如何在如何使用VLC工具播放rtsp视频流了,那么,我们应当如何相关步骤搜索历经看到网络上有一种在浏览器安装插件的方法,但是网友并不推荐,表示有的浏览器版本即便安装了插件也是不支持的;然后又看到第二种方法--后台转成rtmp形式,然后看到网友同样持有不推荐......
  • 常见网络摄像机(摄像头)的端口及RTSP地址
    海康威视默认IP地址:192.168.1.64/DHCP用户名admin密码自己设端口:“HTTP端口”(默认为80)、“RTSP端口”(默认为554)、“HTTPS端口”(默认443)和“服务端口”(默认8000),ONVIF端口80。RTSP地址:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream......
  • 使用rtsp相关流程记录(致健忘的自己)
    相关步骤打开项目下的python文件夹里面的exe文件,双击运行(运行rtsp-simple-server)弹出这样一个界面:在该界面打开的情况下,在idea的Terminal写入相关命令(运行rtsp-simple-server之后,写入命令实现推流)ffmpeg-re-stream_loop-1-iin.mp4-ccopy-frtsprtsp://localhost:85......
  • EasyNTS穿透内网后,海康硬盘录像机拉取不到RTSP流是什么原因?
    EasyNTS上云网关具备内网穿透、组网运维、多协议视频流拉转推、设备/业务上云等功能,它可以解决异地视频共享/组网/上云的需求。其中,EasyNTS上云网关硬件(EasyNTD)可以放置在项目现场,它也同样具备EasyNTS软件平台的功能。有用户反馈,在项目现场利用EasyNTD配合EasyNTS穿透内网,基于海......
  • ZLMediaKit实现按需拉流时rtsp流地址不对addStreamProxy返回0,接口流id参数踩坑记录
    场景开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放:开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rts基于上面实现拉取视频流预览时,发现当调用api传参时如果更换了rtsp视频流地址,但是没有更改流......
  • SpringBoot+Mybatis这个bug估计连作为神仙的您也无法解决--》Invalid bound statement
    最近开发一个调查单的应用系统,加班加点为了解决几个bug,但是最近两天卡在一个bug上。作为一头牛,不能轻易放弃,向困难挑战是牛的精神。1、Invalidbound问题展示首先,我针对题型QuestionType功能,写了五个子功能:增加题型,删除题型,修改题型,查询单条题型,模糊查询多条记录;还写了问题、调查......
  • MFC-SHGetSpecialFolderPath获取指定的系统路径
     CStringstr;TCHARpath[MAX_PATH];BOOLb=SHGetSpecialFolderPath(NULL,path,CSIDL_PROGRAM_FILES_COMMONX86,0);//获取指定的系统路径/*参数1:HWNDhwndOwner窗口所有者的句柄。可以NULL参数2:LPTSTRlpszPath返回路径的缓冲区,该缓......
  • ZLMediaKit实现按需拉流时rtsp流地址不对addStreamProxy返回0,接口流id参数踩坑记录
    场景开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/130136245基于上面实现拉取视频流预览时,发现当调用api传参时如果更换了rtsp视频流地址,但是没有更改......