POJ - 3311 Hie with the Pie(Java JS Python C)

题目来源

3311 -- Hie with the Pie (poj.org)

题目描述

Pizazz披萨店以尽可能快地将披萨送到顾客手中而自豪。

不幸的是,由于削减开支,他们只能雇一个司机来送货。

司机将等待 1 个或更多 (最多10个) 订单被下达后再开始送餐。

不用说,他想要走最短的路线来运送这些食物并返回披萨店,即使这意味着在途中不止一次地经过同一地点或披萨店。

他委托你写一个程序来帮助他。

输入描述

输入将由多个测试用例组成。

  • 第一行将包含单个整数 n,表示要送货的订单数量,其中 1 ≤ n ≤ 10。
  • 在此之后,将有 n + 1 行,每一行包含 n + 1 个整数,表示从披萨店 (编号为0) 到 n 个位置 (编号为 1 到 n)  之间的送餐时间。

    第 i 行上的第 j 个值表示直接从位置 i 到位置 j 而不经过沿途任何其他位置的时间。

请注意,由于不同的速度限制,交通信号灯等,经过其他位置的中转,可能实现更快地从 i 到 j。

此外,时间值可能不对称,即直接从位置 i 到 j 的时间可能与直接从位置 j 到 i 的时间不相同。

输入值 n = 0 将终止输入。

输出描述

对于每个测试用例,您应该输出单个数字,指示交付所有披萨并返回披萨店所需的最短时间。

用例

输入3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
输出8
说明

题目解析

本题第二行~倒数第二行的输入其实就是一个 (n+1) * (n+1) 的邻接矩阵,我们定义其为dist矩阵。

dist[i][j] 表示客户位置 i 到 客户位置 j 的距离。

本题需要我们帮助司机找到一条最短路径,该最短路径需要满足:

  • 从披萨店(位置0)出发,最终返回披萨店
  • 经过所有客户位置,每个客户位置可以经过不止一次

首先,这题需要我们经过所有客户位置,因此我们对 1~n 客户位置求解全排列,每一个全排列即代表一种送餐策略路径,比如n=3,则有以下送餐策略路径:

  • 1->2->3
  • 1->3->2
  • 2->1->3
  • 2->3->1
  • 3->1->2
  • 3->2->1

我们在这些全排列首尾加上0,即可得所有送餐策略路径:

  • 0->1->2->3->0
  • 0->1->3->2->0
  • 0->2->1->3->0
  • 0->2->3->1->0
  • 0->3->1->2->0
  • 0->3->2->1->0

由于本题的 1 ≤ n ≤ 10 ,因此全排列求解不会超时。

得到所有的送餐策略路径后,我们需要求解每种策略路径对应的送餐距离,

如果想要每种策略的送餐距离尽可能小,则我们应该保证路径中相邻两点之间的距离尽可能的小。

而求解图中任意两点间的最短距离,最佳策略是使用floyd算法。

关于floyd算法可以看下:最短路径算法全套(floyed+dijstra+Bellman+SPFA)_哔哩哔哩_bilibili

最终,我们基于floyd算法,求得上面每个全排列路径的最短距离,在这些最短距离中最小的即为题解。

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {while (true) {const n = parseInt(await readline());if (n == 0) break;// floyd算法需要基于dist和path矩阵求解// dist[i][j] 用于记录点 i->j 的最短距离,初始时等价于邻接矩阵const dist = [];// path[i][j] 用于记录点 i->j 最短距离情况下需要经过的中转点,初始时默认任意两点间无中转点,即默认path[i][j] = -1const path = [];for (let i = 0; i < n + 1; i++) {dist.push((await readline()).split(" ").map(Number));path.push(new Array(n + 1).fill(-1));}// floyd算法调用floyd();// ans记录经过所有点后回到出发点的最短距离let ans = Infinity;// 全排列模拟经过所有点的路径dfs(0, 0, new Array(n + 1).fill(false), 0);console.log(ans);// floyd算法求解图中任意两点之间的最短路径function floyd() {for (let k = 0; k < n + 1; k++) {for (let i = 0; i < n + 1; i++) {for (let j = 0; j < n + 1; j++) {// newDist是经过k后,i->j的距离const newDist = dist[i][k] + dist[k][j];// 如果newDist是i->j的更短路径if (newDist < dist[i][j]) {// 则更新i->j的最短距离dist[i][j] = newDist;// 且此更短距离需要经过k, path[i][j]即记录 i->j 最短距离下需要经过点 kpath[i][j] = k;}}}}}/*** 找一条经过所有点的最短路径,我们可以求解所有点形成的全排列,每一个全排列都对应一条经过所有点的路径,只是经过点的先后顺序不同 //* 求某个全排列过程中,可以通过dist数组,累计上一个点i到下一个点j的最短路径dist[i][j]** @param pre 上一个点, 初始为0,表示从披萨店出发* @param sum 当前全排列路径累计的路径权重* @param used 全排列used数组,用于标记哪些点已使用过* @param level 用于记录排列的长度*/function dfs(pre, sum, used, level) {if (level == n) {// 此时pre是最后一个客户所在点,送完最后一个客户后,司机需要回到披萨店,因此最终累计路径权重为 sum + dist[pre][0]// 我们保留最小权重路径ans = Math.min(ans, sum + dist[pre][0]);return;}for (let i = 1; i <= n; i++) {if (used[i]) continue;used[i] = true;dfs(i, sum + dist[pre][i], used, level + 1);used[i] = false;}}}
})();

Java算法源码

import java.util.Scanner;public class Main {static int n;static int[][] dist;static int[][] path;static int ans;public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNextInt()) {n = sc.nextInt();if (n == 0) break;// floyd算法需要基于dist和path矩阵求解// dist[i][j] 用于记录点 i->j 的最短距离,初始时等价于邻接矩阵dist = new int[n + 1][n + 1];// path[i][j] 用于记录点 i->j 最短距离情况下需要经过的中转点,初始时默认任意两点间无中转点,即默认path[i][j] = -1path = new int[n + 1][n + 1];for (int i = 0; i < n + 1; i++) {for (int j = 0; j < n + 1; j++) {dist[i][j] = sc.nextInt();path[i][j] = -1;}}// floyd算法调用floyd();// ans记录经过所有点后回到出发点的最短距离ans = Integer.MAX_VALUE;// 全排列模拟经过所有点的路径dfs(0, 0, new boolean[n + 1], 0);System.out.println(ans);}}// floyd算法求解图中任意两点之间的最短路径public static void floyd() {for (int k = 0; k < n + 1; k++) {for (int i = 0; i < n + 1; i++) {for (int j = 0; j < n + 1; j++) {// newDist是经过k后,i->j的距离int newDist = dist[i][k] + dist[k][j];// 如果newDist是i->j的更短路径if (newDist < dist[i][j]) {// 则更新i->j的最短距离dist[i][j] = newDist;// 且此更短距离需要经过k, path[i][j]即记录 i->j 最短距离下需要经过点 kpath[i][j] = k;}}}}}/*** 找一条经过所有点的最短路径,我们可以求解所有点形成的全排列,每一个全排列都对应一条经过所有点的路径,只是经过点的先后顺序不同 //* 求某个全排列过程中,可以通过dist数组,累计上一个点i到下一个点j的最短路径dist[i][j]** @param pre 上一个点, 初始为0,表示从披萨店出发* @param sum 当前全排列路径累计的路径权重* @param used 全排列used数组,用于标记哪些点已使用过* @param level 用于记录排列的长度*/public static void dfs(int pre, int sum, boolean[] used, int level) {if (level == n) {// 此时pre是最后一个客户所在点,送完最后一个客户后,司机需要回到披萨店,因此最终累计路径权重为 sum + dist[pre][0]// 我们保留最小权重路径ans = Math.min(ans, sum + dist[pre][0]);return;}for (int i = 1; i <= n; i++) {if (used[i]) continue;used[i] = true;dfs(i, sum + dist[pre][i], used, level + 1);used[i] = false;}}
}

Python算法源码

import sys# floyd算法求解图中任意两点之间的最短路径
def floyd():for k in range(n + 1):for i in range(n + 1):for j in range(n + 1):# newDist是经过k后,i->j的距离newDist = dist[i][k] + dist[k][j]# 如果newDist是i->j的更短路径if newDist < dist[i][j]:# 则更新i->j的最短距离dist[i][j] = newDist# 且此更短距离需要经过k, path[i][j]即记录 i->j 最短距离下需要经过点 kpath[i][j] = kdef dfs(pre, sumDis, used, level):"""找一条经过所有点的最短路径,我们可以求解所有点形成的全排列,每一个全排列都对应一条经过所有点的路径,只是经过点的先后顺序不同 //求某个全排列过程中,可以通过dist数组,累计上一个点i到下一个点j的最短路径dist[i][j]:param pre: 上一个点, 初始为0,表示从披萨店出发:param sumDis: 当前全排列路径累计的路径权重:param used: 全排列used数组,用于标记哪些点已使用过:param level: 用于记录排列的长度"""global ansif level == n:# 此时pre是最后一个客户所在点,送完最后一个客户后,司机需要回到披萨店,因此最终累计路径权重为 sum + dist[pre][0]# 我们保留最小权重路径ans = min(ans, sumDis + dist[pre][0])returnfor i in range(1, n + 1):if used[i]:continueused[i] = Truedfs(i, sumDis + dist[pre][i], used, level + 1)used[i] = Falsewhile True:n = int(input())if n == 0:break# floyd算法需要基于dist和path矩阵求解# dist[i][j] 用于记录点 i->j 的最短距离,初始时等价于邻接矩阵dist = [list(map(int, input().split())) for _ in range(n + 1)]# path[i][j] 用于记录点 i->j 最短距离情况下需要经过的中转点,初始时默认任意两点间无中转点,即默认path[i][j] = -1path = [[-1] * (n + 1) for _ in range(n + 1)]# floyd算法调用floyd()# ans记录经过所有点后回到出发点的最短距离ans = sys.maxsize# 全排列模拟经过所有点的路径dfs(0, 0, [False] * (n + 1), 0)print(ans)

C算法源码

POJ的C编译器估计有点老了,很多语法和内置库都无法用,下面是适配修改后可以AC的代码

#include <stdio.h>
#include <limits.h>#define MIN(a,b) ((a) < (b) ? (a) : (b))#define MAX_SIZE 11int n;
int dist[MAX_SIZE][MAX_SIZE];
int path[MAX_SIZE][MAX_SIZE];int ans;
int used[MAX_SIZE];/*** 找一条经过所有点的最短路径,我们可以求解所有点形成的全排列,每一个全排列都对应一条经过所有点的路径,只是经过点的先后顺序不同 //* 求某个全排列过程中,可以通过dist数组,累计上一个点i到下一个点j的最短路径dist[i][j]** @param pre 上一个点, 初始为0,表示从披萨店出发* @param sum 当前全排列路径累计的路径权重* @param used 全排列used数组,用于标记哪些点已使用过* @param level 用于记录排列的长度*/
void dfs(int pre, int sum, int used[], int level) {int i;if (level == n) {// 此时pre是最后一个客户所在点,送完最后一个客户后,司机需要回到披萨店,因此最终累计路径权重为 sum + dist[pre][0]// 我们保留最小权重路径ans = MIN(ans, sum + dist[pre][0]);return;}for (i = 1; i <= n; i++) {if (used[i]) continue;used[i] = 1;dfs(i, sum + dist[pre][i], used, level + 1);used[i] = 0;}
}// floyd算法求解图中任意两点之间的最短路径
void floyd() {int i, j, k;for (k = 0; k < n + 1; k++) {for (i = 0; i < n + 1; i++) {for (j = 0; j < n + 1; j++) {// newDist是经过k后,i->j的距离int newDist = dist[i][k] + dist[k][j];// 如果newDist是i->j的更短路径if (newDist < dist[i][j]) {// 则更新i->j的最短距离dist[i][j] = newDist;// 且此更短距离需要经过k, path[i][j]即记录 i->j 最短距离下需要经过点 kpath[i][j] = k;}}}}
}int main() {while (1) {int i, j;scanf("%d", &n);if (n == 0) {break;}// floyd算法需要基于dist和path矩阵求解for (i = 0; i < n + 1; i++) {for (j = 0; j < n + 1; j++) {// dist[i][j] 用于记录点 i->j 的最短距离,初始时等价于邻接矩阵scanf("%d", &dist[i][j]);// path[i][j] 用于记录点 i->j 最短距离情况下需要经过的中转点,初始时默认任意两点间无中转点,即默认path[i][j] = -1path[i][j] = -1;}}// floyd算法调用floyd();// ans记录经过所有点后回到出发点的最短距离ans = INT_MAX;// 全排列模拟经过所有点的路径for (i = 0; i < n + 1; i++) used[i] = 0;dfs(0, 0, used, 0);printf("%d\n", ans);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第12章 项目质量管理

文章目录 项目质量管理包括把组织的质量政策应用于规划、管理、控制项目和产品质量要求&#xff0c;以满足干系人目标的各个过程。此外&#xff0c;项目质量管理以执行组织的名义支持过程的待续改进活动。 12.1管理基础 12.1.1质量与项目质量 1质量 国际标准化组织(ISO)对质量…

用于垃圾回收的运行时配置选项

反馈 本文内容 指定配置的方法垃圾回收的风格管理资源使用情况大型页面 显示另外 4 个 此页面包含有关 .NET 运行时垃圾回收器 (GC) 设置的信息。 如果你要尝试让正在运行的应用达到最佳性能&#xff0c;请考虑使用这些设置。 然而&#xff0c;在特定情况下&#xff0c;默认…

基于大整形的运算收录

目录 目录 目录 前言 为什么要大整数 大整形的加/减法 大整形的乘法 大整形除法 大整形开方 代码实现 前言 好久没有更新博客了&#xff0c;hhh。时隔三个月&#xff0c;我又回来了。先来点简单的大整形&#xff0c;虽说简单&#xff0c;但是在编写的时候还是debug了…

学校门禁管理技巧,一招轻松学会!

随着社会的不断发展和科技的不断进步&#xff0c;安全管理成为各个领域至关重要的议题之一。门禁监控系统作为现代安全管理的关键组成部分&#xff0c;不仅为建筑物提供了有效的访问控制&#xff0c;还在提高整体安全性和管理效率方面发挥了关键作用。 客户案例 公司办公楼门禁…

C# 用于准确地测量运行时间的Stopwatch中.Start 方法和Stopwatch.Stop 方法

一、Stopwatch 类 提供一组方法和属性&#xff0c;可用于准确地测量运行时间。 public class Stopwatch 使用 Stopwatch 类来确定应用程序的执行时间。 // 使用 Stopwatch 类来确定应用程序的执行时间 using System.Diagnostics; class Program {static void Main(string[] a…

php no input file specified

一、修改 .user.ini 文件 内容 open_basedir/wab/led-sportslight.com/:/tmp/ led-sportslight.com是项目根目录位置 改好后保存并清空缓存硬刷新网站就行了 二、mkdir(): Permission denied /core/library/think/cache/driver/File.php 第 84 行左右 mkdir(): Permission de…

2024最新最全【网络安全面试题含答案】(非常详细),零基础入门到精通

防范常见的 Web 攻击 什么是SQL注入攻击 攻击者在HTTP请求中注入恶意的SQL代码&#xff0c;服务器使用参数构建数据库SQL命令时&#xff0c;恶意SQL被一起构造&#xff0c;并在数据库中执行。 用户登录&#xff0c;输入用户名 lianggzone&#xff0c;密码 ‘ or ‘1’’1 &a…

力扣刷题第八天 最大交换

给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。注意: 给定数字的范围是 [0, 10^8] 方法一&#xff1a;直接遍历 由于对…

使用 OpenCV 添加(混合)两个图像

目标 在本教程中&#xff0c;您将学习&#xff1a; 什么是线性混合以及为什么它有用;如何使用 addWeighted&#xff08;&#xff09; 添加两个图像 理论 注意 下面的解释属于Richard Szeliski的《计算机视觉&#xff1a;算法和应用》一书 从我们之前的教程中&#xff0c;…

LabVIEW扫描探针显微镜系统开发

在纳米技术对高精度材料特性测量的需求日益增长。介绍了基于LabVIEW开发的扫描探针显微镜&#xff08;SPM&#xff09;系统。该系统不仅可以高效地测量材料的热物性&#xff0c;还能在纳米尺度上探究热电性质&#xff0c;为材料研究提供了强大的工具。 系统基于扫描探针显微技…

(2)(2.1) Andruav Android Cellular(二)

文章目录 前言 5 Andruav Web Client 6 Andruav Telemetry 7 Andruav高级功能 8 将Andruav与SITL配合使用 9 FAQ 10 术语表 前言 Andruav 是一个基于安卓的互联系统&#xff0c;它将安卓手机作为公司计算机&#xff0c;为你的无人机和遥控车增添先进功能。 5 Andruav W…

数学建模--PageRank算法的Python实现

文章目录 1. P a g e R a n k PageRank PageRank算法背景2. P a g e R a n k PageRank PageRank算法基础2.1. P a g e R a n k PageRank PageRank问题描述2.2.有向图模型2.3.随机游走模型 3. P a g e R a n k PageRank PageRank算法定义3.1. P a g e R a n k PageRank PageRank…

GD32接收不定长数据包

接收不定长数据 Cubemx生成代码过程忽略 首先在main函数中创建接收缓存区 并在main.h中定义 接下来就是重写串口的中断函数中的内容&#xff0c;把原有内容注释掉 main中创建一个记录接收数据长度的变量和标志位 然后再在主函数中添加一个验证代码&#xff0c;这样MCU收到数据…

Cesium叠加超图二维服务、三维场景模型

前言 Cesium作为开源的库要加超图的服务则需要适配层去桥接超图与Cesium的数据格式。这个工作iClient系列已经做好&#xff0c;相比用过超图二维的道友们可以理解&#xff1a;要用Openlayer加载超图二维&#xff0c;那就用iClient for Openlayer库去加载&#xff1b;同样的要用…

el-table导出表格文件

先写一个download公共的方法 download(file) {const blob fileconst blobURL window.URL ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob)const a document.createElement(a)a.download 故障的报表.xlsxa.href blobURLdocument.body.appen…

Git与GitHub零基础教学

大家好&#xff0c;我是星恒&#xff0c;这个帖子给大家分享的是git和github的全套教程&#xff0c;包含github初始&#xff0c;git常用命令以及基本使用&#xff0c;git的ssh链接github&#xff0c;github使用token登录&#xff0c;github和idea的配合&#xff0c;一些平时常用…

Flink编程——基础环境搭建

基础环境搭建 文章目录 基础环境搭建准备环境搭建源码环境搭建克隆代码编译导入IDEA 集群环境搭建本地模式安装步骤 1&#xff1a;下载步骤 2&#xff1a;启动集群步骤 3&#xff1a;提交作业&#xff08;Job&#xff09;步骤 4&#xff1a;停止集群 总结 准备环境搭建 我们先…

我们需要练习关爱自己,让自己松弛下来,而练习的方式就是慈心,祝福自己也祝福他人

非常正确&#xff01;关爱自己是维持身心健康的关键之一。通过慈心和祝福的方式&#xff0c;我们可以培养更积极、更宽容的心态&#xff0c;提升生活质量。以下是一些建议&#xff0c;帮助你在日常生活中练习关爱自己&#xff1a; 自我体谅&#xff1a; 对待自己要像对待朋友一…

国内SAP实施公司大盘点

随着企业数字化转型的加速推进&#xff0c;SAP作为全球有名的企业软件解决方案提供商&#xff0c;受到了越来越多企业的青睐。然而&#xff0c;要充分发挥SAP软件的潜力&#xff0c;企业需要依赖专业的SAP实施公司来提供技术支持和咨询服务。在国内&#xff0c;有许多优秀的SAP…

Spring ApplicationContext

ApplicationContext 在 Spring 中代表着一个高级的 IoC 容器&#xff0c;负责实例化、配置和组装对象。ApplicationContext 接口扩展自 BeanFactory 接口&#xff0c;添加了更多的企业级功能&#xff0c;比如更容易的国际化、事件传播、资源加载等。 ApplicationContext 接口关…