POJ旅行商问题——解题报告
旅行商问题
总时间限制: 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旅行商问题——解题报告的更多相关文章
- POJ 1001 解题报告 高精度大整数乘法模版
题目是POJ1001 Exponentiation 虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...
- poj分类解题报告索引
图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Jou ...
- POJ 1003 解题报告
1.问题描述: http://poj.org/problem?id=1003 2.解题思路: 最直观的的想法是看能不能够直接求出一个通项式,然后直接算就好了, 但是这样好水的样子,而且也不知道这个通项 ...
- POJ 1004 解题报告
1.题目描述: http://poj.org/problem?id=1004 2.解题过程 这个题目咋一看很简单,虽然最终要解出来的确也不难,但是还是稍微有些小把戏在里面,其中最大的把戏就是float ...
- POJ 1005 解题报告
1.题目描述 2.解题思路 好吧,这是个水题,我的目的暂时是把poj第一页刷之,所以水题也写写吧,这个题简单数学常识而已,给定坐标(x,y),易知当圆心为(0,0)时,半圆面积为0.5*PI*(x ...
- POJ 3414 解题报告!
原题: Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13227 Accepted: 5550 Special Jud ...
- POJ 2411 解题报告
传送门:http://poj.org/problem?id=2411 题目简述 有一个\(W\)行\(H\)列的广场,需要用\(1*2\)小砖铺满,小砖之间互相不能重叠,问 有多少种不同的铺法? 输入 ...
- 广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
题目链接:http://poj.org/problem?id=3411 题目意思:N个city 由 m 条路连接,对于一条路(假设连接Cityia和 Cityb),如果从Citya 去 Cityb的途 ...
- POJ 2182 解题报告
Lost Cows Time Limit: 1000 MS Memory Limit: 65536 KB Description N (2 <= N <= 8,000) cows have ...
随机推荐
- sql的练习题
表名和字段 –1.学生表 Student(s_id,s_name,s_birth,s_sex) --学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_i ...
- 2020年,MyBatis常见面试题总结
Mybatis 技术内幕系列博客,从原理和源码角度,介绍了其内部实现细节,无论是写的好与不好,我确实是用心写了,由于并不是介绍如何使用 Mybatis 的文章,所以,一些参数使用细节略掉了,我们的目标 ...
- iMX287A多种方法实现流水灯效果
目录 1.流水灯在电子电路中的地位 2.硬件电路分析 3.先点个灯吧 4.shell脚本实现流水灯 5.ANSI C文件操作实现流水灯 6.Linux 系统调用实现流水灯 @ 1.流水灯在电子电路中的 ...
- PHP算法练习2:(175. 组合两个表)
练习地址:https://leetcode-cn.com/problems/combine-two-tables/ 表1: Person +-------------+---------+ | 列名 ...
- LeetCode python实现题解(持续更新)
目录 LeetCode Python实现算法简介 0001 两数之和 0002 两数相加 0003 无重复字符的最长子串 0004 寻找两个有序数组的中位数 0005 最长回文子串 0006 Z字型变 ...
- 2020年春招面试必备Spring系列面试题129道(附答案解析)
前言 关于Spring的知识总结了个思维导图分享给大家 1.不同版本的 Spring Framework 有哪些主要功能? 2.什么是 Spring Framework? Spring 是一个 ...
- Vue+Axios+iview+vue-router实战管理系统项目
项目实现登陆验证,iviewui组件使用,vue-router路由拦截,在删除登陆存储的token后,直接路由进登陆页面,实战数据请求,本地data.json,笔者也是初出茅庐,在项目运行后,会一直c ...
- 【技巧】歪脑筋优化flexbox瀑布流布局方案
效果先行 需求 在大量"不定宽"元素并排的布局模式下,上图是我们想要的最佳布局但是FlexBox布局虽然枪弹但并不能完全呈现以上布局,于是我们需要结合FlexBox作下小的改动即可 ...
- Postgresql存放数组形式的数据
Postgres 数据库允许把字段定义为可变长度的数组.数据类型既可以是内置类型,也可以是用户自定义的类型或枚举类型. 例如: 创建表 create table demo(name text,subj ...
- centos7搭建ceph集群
一.服务器规划 主机名 主机IP 磁盘配比 角色 node1 public-ip:10.0.0.130cluster-ip:192.168.2.130 sda,sdb,sdcsda是系统盘,另外两块数 ...