中国邮递员问题+代码实现(cpp)

article/2025/10/8 7:31:24

       中国邮递员问题是一个和旅行商问题比较相关但又不太相同的一个问题,而且个人感觉理解的难度更大一点,当然,这就是仁者见仁,智者见智了,旅行商问题是不能回头的,一个节点访问过了不能回来了,并不需要走完所有的路,但是中国邮递员问题可以多次访问一个节点,因为中国邮递员问题要求的是要访问所有的街道,即,每条街道必须访问到。在这样的前提下,如果规划路径使得返回邮局时路程最短。

       试想,假设每条路都走一次,最终恰好还能返回出发点,这样的拓扑图画出来应该满足怎样的结构呢?每个节点要进去还要出去,所以,每个点的入度和出度必须相等(起始点也一样),也就是说,每个节点的度应该是偶数个,满足这样的拓扑结构的图就是欧拉回路。如下图所示:

 每个节点入度出度一定相同,所以总的度就是偶数。

但是,在实际生活中,或者实际拓扑中,节点的度很可能不是奇数个,因此,这也是解决中国邮递员问题最重要的一步,构造欧拉回路。

一个拓扑结构可以构造出很多个欧拉回路,但是,我们这道题要求的最短的路径,而原有的路径一定都是,所以,构造欧拉回路的边决定了最终的结果。

基于上述理解,判断是否为欧拉回路,如果是,直接相加返回结果,如果不是,那存在奇数度的节点一定有偶数个,如何选择更好的构造方案也成为了解决该问题第二个重要的点。

构造欧拉回路:

如上图所示,V8,V2,V4,V6都是奇数度点,因此,将这些点进行标记,来构造欧拉回路。

如下图所示,各种方案:

这几种方案都是构造欧拉回路的方案,但是,相对比会发现,只有最后一个是最优的结果,那如何得到最优结果呢,其实需要以下步骤来得到最优结果:

1、根据统计每个节点度的数目,标记出奇数度的节点。

2、奇数节点一定是有偶数个,因此,最终的距离应该是:两两点之间的最短距离,而两两点之间的最短距离可以用Floyd或者Dijkstra或者bellman-ford算法来得到。个人建议使用Floyd算法,不容易出错。

3、遍历所有的组合情况,求出最短的组合方式,例如比较 d(2,8)+d(4,6),d(2,6)+d(4,8), d(2,4)+d(6,8), 然后取最小值即为最终的优化方案:d(2,8)+d(4,6)。求解该步骤的时候,可以使用DFS来寻找最短路径方案,也可以利用DFS的思想,改为动态规划来实现,在别的博客上看到状压dp的字眼,应该是说这块的东西。动态规划思路的代码相对没有DFS更符合人们的思路,答题思路是构造一个dp表,行值为1,列值表示该集合中所含的元素,例如:集合7表示所含元素在奇度数组中下标为{1, 2, 3}的集合,即为二进制表示下,哪个位置为1,就含有对应的点,在这种方法下,为了方便操作,一般在邮递员问题中,点的编号是从1开始的,而求解的顺序应该是先求解小集合,再求解大集合,举个例子:假设现在得到的奇数度点的数组为:[2,4,6,8](为了代码方便,实际上该数组在后续代码的实现上是[0,2,4,6,8]),一共有四个有效点,则dp数组应为1×16的规模,dp[0]表示一个点也没有的集合,空集自然距离也为0,而更大集合j的最短距离值应该由更小的集合i及不在i中的两个点x,y求得,举个例子,当求出集合3({2, 4})的最短距离时,记录在dp[3]中,而集合15({2,4,6,8})的最短距离可以用dp[3]+d[6][8]来完成更新,如果dp[3]+d[6][8]<dp[15],则更新dp[15]。同理,当求出集合5({2,6})的最短距离时,记录在dp[5]中,则可以用dp[5]+d[4][8]<dp[15],则更新dp[15],该动态规划算法通过利用小数据集更新大数据集的距离,最终返回dp的最后一个值作为最优路径的结果。

最终的方案结果是:原图中的所有路径+构造时新添加的路径。

方案步骤:

1、生成邻接矩阵,利用Floyd算法求出每两个点之间的最短距离。(Floyd)

2、判断整个过程是否是欧拉回路,如果不是构造欧拉回路。

3、利用动态规划或者DFS计算构造欧拉回路的最优方案。

4、计算原路径与新构造路径的长度总和即为最终结果。

以下是参考代码:

步骤一:Floyd

    void Floyd (vector<vector<int>>& graph, int N) {for (int k=1; k<=N; ++k) {for (int i=1; i<=N; ++i) {for (int j=1; j<=N; ++j) {if (i == j) {continue;}if (graph[i][k]!=-1 && graph[k][j]!=-1) {graph[i][j] = graph[i][j]==-1 ? graph[i][k]+graph[k][j] : min (graph[i][j], graph[i][k]+graph[k][j]);}}}}}

这里要说明,我的程序中,-1表示路不通,所以加了一些判断条件,看上去比较复杂,其实也可以将数值定义成比较大的值,代码就比较简单,但是那样做有时候有越界危险。

步骤二:

    int shortestPath (vector<vector<int>>& graph, vector<int>& dev, int N) {Floyd (graph, N);vector<int> odds;odds.push_back(0);for (int i=1; i<=N; ++i) {if (dev[i]&1) {odds.push_back(i);}}int res = 0;int ods = odds.size()-1;vector<int> dp((1<<ods), -1);dp[0] = 0;for (int i=0; i<(1<<ods); ++i) {int x = 1;while ((1<<(x-1)) & i) {++x;}for (int y=x+1; y<=ods; ++y) {if ((1<<(y-1)) & i) {continue;}dp[i|(1<<(x-1))|(1<<(y-1))] = dp[i] != -1 && graph[odds[x]][odds[y]] != -1 ? dp[i|(1<<(x-1))|(1<<(y-1))] == -1 ? dp[i]+graph[odds[x]][odds[y]] : min(dp[i|(1<<(x-1))|(1<<(y-1))], dp[i]+graph[odds[x]][odds[y]]) : dp[i|(1<<(x-1))|(1<<(y-1))];}}for (int i=0; i<(1<<ods); ++i) {cout << dp[i] << " ";}cout << endl;cout << dp[(1<<ods)-1] << endl;return dp[(1<<ods)-1];}

该程序中,graph是已经求得的最短路径结果,数组dev记录的是所有节点的度,我们在下面的程序中,选择奇数度的节点组成odds数组,而后构建dp数组,通过小的集合i,以及不在i中的两点x和y计算更大的集合j的距离,通过多次迭代求出最优结果,因为我的dp初始化都是-1,也就是说-1在程序中的含义表示无限大,不可行的意思,所以要加一些比较细节的判断。

以下是整个程序的代码:

#include <bits/stdc++.h>using namespace std;class Solution {
private:void Floyd (vector<vector<int>>& graph, int N) {for (int k=1; k<=N; ++k) {for (int i=1; i<=N; ++i) {for (int j=1; j<=N; ++j) {if (i == j) {continue;}if (graph[i][k]!=-1 && graph[k][j]!=-1) {graph[i][j] = graph[i][j]==-1 ? graph[i][k]+graph[k][j] : min (graph[i][j], graph[i][k]+graph[k][j]);}}}}}public:int shortestPath (vector<vector<int>>& graph, vector<int>& dev, int N) {Floyd (graph, N);vector<int> odds;odds.push_back(0);for (int i=1; i<=N; ++i) {if (dev[i]&1) {odds.push_back(i);}}int res = 0;int ods = odds.size()-1;vector<int> dp((1<<ods), -1);dp[0] = 0;for (int i=0; i<(1<<ods); ++i) {int x = 1;while ((1<<(x-1)) & i) {++x;}for (int y=x+1; y<=ods; ++y) {if ((1<<(y-1)) & i) {continue;}dp[i|(1<<(x-1))|(1<<(y-1))] = dp[i] != -1 && graph[odds[x]][odds[y]] != -1 ? dp[i|(1<<(x-1))|(1<<(y-1))] == -1 ? dp[i]+graph[odds[x]][odds[y]] : min(dp[i|(1<<(x-1))|(1<<(y-1))], dp[i]+graph[odds[x]][odds[y]]) : dp[i|(1<<(x-1))|(1<<(y-1))];}}return dp[(1<<ods)-1];}
};int main()
{int N = 4, R = 5;//cin >> N >> R;//vector<vector<int>> routes(R, vector<int> (3, 0));vector<vector<int>> graph (N+1, vector<int> (N+1, -1));vector<int> dev (N+1, 0);int res = 0;//vector<vector<int>> routes(R, vector<int> (3, 0));vector<vector<int>> routes = {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {1, 4, 10}, {1, 3, 12}};for (int i=0; i<R; ++i) {int x = routes[i][0], y = routes[i][1], z = routes[i][2];//cin >> x >> y >> z;graph[x][y] = z;graph[y][x] = z;++dev[x];  ++dev[y];res += z;}cout << res << endl;Solution solve;res += solve.shortestPath (graph, dev, N);return 0;
}

 


http://chatgpt.dhexx.cn/article/yH7p5VCS.shtml

相关文章

离散数学实验----中国邮递员问题

实验目的和要求 实验目的&#xff1a; 理解什么是欧拉图&#xff0c;熟悉欧拉路和欧拉回路的概念。掌握Dijkstra算法&#xff0c;求解最短路径掌握Fleury算法&#xff0c;求解欧拉回路。了解Edmonds-Johnson算法解决中国邮递员问题的基本思路。通过程序实现中国邮递员问题&…

数据结构——中国邮递员问题

问题描述 代码 #include <stdio.h> #include <stdlib.h> #include <string.h>#define min(a,b) ( (a) < (b) ? (a) : (b) ) #define MAX_NODE 100 #define MAX_EDGE 100 #define INF 0x7fffffff // 表示两点不连通typedef struct {int number; …

[算法导论] 邮递员问题

邮递员问题 旅行商问题&#xff1a;给定一系列城市和每对城市之间的距离&#xff0c;求解访问每一座城市一次并回到起始城市的最短回路。&#xff08;遍历点&#xff0c;回到起点&#xff09; 哈密顿路径 哈密顿图 中国邮递员问题&#xff1a;邮差要设法找到一条最短路径&…

中国邮递员问题的深入剖析与算法实现(附例题及MATLAB、LINGO代码)

中国邮递员问题的深入剖析与算法实现 一、研究背景1.1 哥尼斯堡七桥问题1.2 欧拉图1.3 中国邮递员问题 二、中国邮递员问题深入解读2.1 问题重述2.2 奇偶点图上作业法[^1]2.3 最小二分匹配法1) 针对无向图2) 针对有向图 2.4 $fleury$算法 三、经典中国邮递员问题的具体实现3.1 …

中国邮路算法(中国邮递员问题)(详细)

通路&#xff1a;在无向图中由点边交替组成的序列就是通路&#xff08;如果这个图是简单的&#xff0c;那么也可以使用点的序列来表示&#xff09;&#xff0c;如果首尾的点相同&#xff0c;则称为一条回路 无向图的连通性&#xff1a;无向图中任意一对点之间均有通路 欧拉通路…

那些有趣的网站

之前分享过那些有意思的网站 &#xff0c;这里继续分享一波&#xff0c;也许你用得上。 福利单词 一边背单词一边看妹子的网站&#xff0c;用电脑打开&#xff0c;配合ctrlw 关闭新窗口&#xff0c;不知不觉就背了百来个词了 https://easychen.gitee.io/foxdict/ 工资计算器 简…

常用又有趣的网站大合集

〇、【Python challenge】通关代码及攻略 一、PIECES 拼图 PIECES 拼图网站用 30 个 CSS 碎片进行拼图&#xff0c;向我们呈现了 30 种濒临灭绝的动物。 二、小甲鱼编程学习工作室 包含了各种编程语言学习以及计算机基本操作的教学与奇技淫巧 三、Wolfram Alpha 这是由Wol…

超酷的13个CSS有趣学习网站

13个CSS有趣学习网站 今天来给大家推荐13个辅助你学习巩固知识的网站&#xff0c;让你边玩边学边记&#xff01; 因为这些网站大多都是国外的大佬们做的&#xff0c;所以网页大多都是英文&#xff0c;为了更好地使用&#xff0c;给你们推荐两个翻译的方式&#xff1a; 使用C…

电脑技巧:盘点10个非常实用且有趣的网站

目录 1、聆听大海的声音 2、在线生成Logo 3、今日热榜 4、十万个为什么&#xff08;大人版&#xff09; 5、视频创作导航 6、改图鸭 7、好看电影推荐 8、童年游戏合集 9、各种沙雕表情包 10、反向词典 今天给大家分享10个非常实用且有趣的网站&#xff0c;值得收藏&a…

科普:如何找到有趣的网站?

原址&#xff1a;http://shedingkong.lofter.com/post/302b9d_1943cf2# 其实我发各种网站的推荐&#xff0c;是为了给自己留用&#xff0c;也是因为现在的审查环境下&#xff0c;各种下载资源的分享十分痛苦。总有人问我怎么知道这么多网站&#xff0c;这里来介绍几种方法。 方…

你是否看到过如此有趣的AI网站?

1、营销文案&#xff1a;CopyAI: Create Marketing Copy In Seconds 2、美化ppt设计&#xff1a;https://www.beautiful.ai/ 3、图片修改&#xff1a;https://hotpot.ai 4、照片变视频&#xff1a;https://www.myheritage.com/deep-nostalgia 美化头像&#xff1a;Free Profil…

有趣好玩的python编程网站

✅作者简介&#xff1a;大家好我是hacker707,大家可以叫我hacker &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;python &#x1f4ac;推荐一款模拟面试、刷题神器&#x1f449;点击跳转进入网站 整理了一些非常有意思&#xff0c;适…

有趣的表白网站

今天看到一个傻瓜式的表白网址生成网站&#xff0c;觉得还挺有意思的&#xff0c;所以来分享一下。http://www.51bbw.cn/show/ 进入网址就会看到下面的界面&#xff1a; 然后就可以“量力而行”了&#xff0c;依据财力选择你想制作的模板&#xff0c;老白嫖怪一眼看中了“免费…

有趣的网站

黑客帝国文字雨生成器 AirPano 足不出户的旅行 创客贴 自媒体制图神器

实时查看Starlink在轨卫星、地面站数目和分布情况的有趣网站

记录一些SpaceX的Starlink相关的一些有趣有用小网站~ 一、实时查看Starlink在轨卫星数目和分布情况 https://satellitemap.space/ 除了可以看Starlink的&#xff0c;还可以看OneWeb和GPS的在轨卫星和分布情况&#xff1b; 截止到2022-4-23&#xff0c;共有卫星2283颗&#xf…

收藏全球最有趣的网站 (上)

在线玩转指尖陀螺-FFFFidget ←点击评分&#xff0c;有趣指数&#xff1a; 3.40星 风靡全球的指间小玩具&#xff01;网站可以在线体验指尖陀螺的迷之旋转&#xff0c;同时支持PC和移动端&#xff0c;手机玩起来更带感&#xff01; 传送门 http://ffffidget.com/ 继续阅读 →…

几个有创意有趣的网站推荐

几个有趣的网站推荐&#xff0c;这些网站很有创意&#xff0c;第一眼就很惊艳 都能打开&#xff0c;不过速度有点慢&#xff0c;一定要有耐心等待&#xff0c;因为有几个是国外的网站&#xff0c;如果是在手机上打开的&#xff0c;复制地址进浏览器 1、Marco Gomez &#xff0d…

记录一些有趣网站

https://css-tricks.com/ 2018.01.15更 腾讯游戏官方设计团队 http://tgideas.qq.com/?ADTAGmedia.gameweb.console 2018.01.16更 该文档库&#xff1a;http://tgideas.qq.com/doc/ 里面有个相关的一些干货 王者荣耀网站帮助管理平台 https://pvp.qq.com…

一个神奇的资源网站「有趣网站收藏家」共有186个站点资源-北忘山修改版

一个神奇的资源网站「有趣网站收藏家」共有186个站点资源-北忘山修改版 网站介绍 这个网站有点东西&#xff0c;目前收集了186个资源&#xff0c;小北当时拔下来之后发现都是作者纯html手写的&#xff0c;意思就是每每添加网站都是手动添加上去。小北整下来之后&#xff0c;做了…

有趣的网站合集

导航页面 1、有趣网址之家 – 收藏全球最有趣的网站 https://youquhome.com/ 一、电子图书及公开课程 1、国图公开课 依托国家图书馆宏富的馆藏资源&#xff0c;以服务国家战略、传播中华优秀传统文化、提高公众文化生活品质为主线。一方面整合多种文献资源&#xff0c;并结…