旅行商问题

总时间限制: 1000ms 内存限制: 65536kB

描述

某国家有n(1<=n<=10)座城市,给定任意两座城市间距离(不超过1000的非负整数)。一个旅行商人希望访问每座城市恰好一次(出发地任选,且最终无需返回出发地)。求最短的路径长度。

输入

第一行输入一个整数n

接下来n行,每行n个数,用空格隔开,以邻接矩阵形式给出城市间距离。该邻接矩阵是对称的,且对角线上全为0

输出

一行,最短路径的长度

样例输入
6
0 16 1 10 12 15
16 0 10 2 10 8
1 10 0 10 5 10
10 2 10 0 9 3
12 10 5 9 0 8
15 8 10 3 8 0
样例输出
19

解题思路

这个问题可以抽象为在\(n\)阶无向完全图\(K_n\)中,给定每个边加权(长度),然后在该带权图中求一条权和最小的哈密顿通路(只求解最小权和即可)。我的想法是使用深度优先搜索求解,过程中使用了set来储存通路的长度,由于set使用二叉搜索树,可以在\(O(\log n)\)时间内完成元素插入,同时自动对元素排序,并且能够在\(O(1)\)时间内获得集合的最大和最小值,以略微节省运算时间。另外使用stack容器来临时储存全局变量sum(长度和)的值。

代码
#include <bits/stdc++.h>
using namespace std;
int cities[12][12] = {};
bool visited[12] = {};
//标记去过的城市,如果去过了,则记true
int n;
int sum;
set<int> path;
stack<int> temp;
void dfs(int start)
{
bool flag = true;
for (int i = 1; i <= n; i++)
if (!visited[i])
flag = false;
if (flag)
{
path.insert(sum);
return;
}
//设置边界
//如果没到递归边界,继续
for (int i = 1; i <= n; i++)
{
if (visited[i] == false)
{
visited[i] = true;
if (sum > *path.begin() && path.size() != 0)
{
visited[i] = false;
continue;
}
temp.push(sum);
sum += cities[start][i];
dfs(i);
sum = temp.top();
temp.pop();
visited[i] = false;
}
}
} int main()
{
scanf("%d", &n);
sum = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf("%d", &cities[i][j]);
for (int i = 1; i <= n; i++)
dfs(i);
printf("%d\n", *path.begin());
return 0;
}
其他想法

由于此题中旅行商可以从任意城市出发,我在解题的过程中分别搜索了\(n\)个不同起点的解。但可以看出,搜索的不同路径中有大量重和部分,虽然对那些不可能成为最优解的路径进行了剪枝,搜索的效率仍然不高。

于是便有了另外一种思路,即,在图中先搜索出一条最短的哈密顿回路,然后删去这条回路中的最长边,便得到一条哈密顿通路。由最短的哈密顿回路得到的这条哈密顿通路是否是最短的哈密顿回路,我并没有进行严格的证明。

POJ旅行商问题——解题报告的更多相关文章

  1. POJ 1001 解题报告 高精度大整数乘法模版

    题目是POJ1001 Exponentiation  虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...

  2. poj分类解题报告索引

    图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Jou ...

  3. POJ 1003 解题报告

    1.问题描述: http://poj.org/problem?id=1003 2.解题思路: 最直观的的想法是看能不能够直接求出一个通项式,然后直接算就好了, 但是这样好水的样子,而且也不知道这个通项 ...

  4. POJ 1004 解题报告

    1.题目描述: http://poj.org/problem?id=1004 2.解题过程 这个题目咋一看很简单,虽然最终要解出来的确也不难,但是还是稍微有些小把戏在里面,其中最大的把戏就是float ...

  5. POJ 1005 解题报告

    1.题目描述   2.解题思路 好吧,这是个水题,我的目的暂时是把poj第一页刷之,所以水题也写写吧,这个题简单数学常识而已,给定坐标(x,y),易知当圆心为(0,0)时,半圆面积为0.5*PI*(x ...

  6. POJ 3414 解题报告!

    原题: Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13227 Accepted: 5550 Special Jud ...

  7. POJ 2411 解题报告

    传送门:http://poj.org/problem?id=2411 题目简述 有一个\(W\)行\(H\)列的广场,需要用\(1*2\)小砖铺满,小砖之间互相不能重叠,问 有多少种不同的铺法? 输入 ...

  8. 广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告

    题目链接:http://poj.org/problem?id=3411 题目意思:N个city 由 m 条路连接,对于一条路(假设连接Cityia和 Cityb),如果从Citya 去 Cityb的途 ...

  9. POJ 2182 解题报告

    Lost Cows Time Limit: 1000 MS Memory Limit: 65536 KB Description N (2 <= N <= 8,000) cows have ...

随机推荐

  1. 如何优雅地删除 Linux 中的垃圾文件

    不知道大家是否也跟我一样,是一只要把的自己电脑文件安排的条理有序,把没用的文件会及时删掉的程序猿呢?如果是的话,那么我们可以愉快地探讨下文章的内容.如果不是的话,你也可以留下来凑凑热闹嘛(>-& ...

  2. 【Amaple教程】5. 插件

    Amaple 拥有非常强大插件功能,这也是它的突出功能之一,Amaple插件一般表现为功能块(函数)或功能块(包含一系列函数和属性的Object对象),它除了支持Amaple规范定义的插件外,还支持所 ...

  3. JZOJ 5230. 【NOIP2017模拟A组模拟8.5】队伍统计

    5230. [NOIP2017模拟A组模拟8.5]队伍统计 (File IO): input:count.in output:count.out Time Limits: 1500 ms Memory ...

  4. JZOJ 1774. 合并果子 (Standard IO)

    1774. 合并果子 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Description 在一个果园里,多多已经将所有的果子打 ...

  5. php -v 找不到命令

    [root@localhost htdocs]# php -v -bash: php: command not found export PATH=$PATH:/usr/local/php7/bin ...

  6. nes 红白机模拟器 第7篇 编译使用方法

    模拟器,基于 InfoNES ,作者添加修改以下功能: 1, joypad 真实手柄驱动程序(字符型设备驱动) 2,原始图像只有256*240 ,添加 图像放大算法,这里实现了2种,a, 最近邻插值 ...

  7. C语言程序设计(三) 简单的算术运算和表达式

    第三章 简单的算术运算和表达式 算数运算符:一元.二元.三元(条件运算符) 1/2是整型除法,1.0/2是浮点数除法 求余运算(%)限定参与运算的两个操作数必须为整数,不能对两个实型数据进行求余运算 ...

  8. Python专题——五分钟带你了解map、reduce和filter

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题第6篇文章,给大家介绍的是Python当中三个非常神奇的方法:map.reduce和filter. 不知道大家看到ma ...

  9. Cinemachine中噪音的应用

    两种默认产生噪音的方式 Nosie阶段的Component   Component在流水线中主要通过MuteCameraState来处理对State的计算.   对于Noise类型的Component ...

  10. 使用Filter来过滤掉需要排除的数组对象

    问题描述:有个地方需要根据判断是否是总分公司来控制转正入口的显影,list是获取到的所有入口的数组,需要判断数组里哪个对象的title为"员工转正",本来打算用for循环的,之后发 ...