手电筒过桥问题详解

这是个很经典的问题,但是我看了很多讲解都感觉不是很系统,但是受到了看的讲解的启发,在这里希望写一个比较严谨系统的讲解。

题目是这样的:在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时通过。如果各自单独过桥的话,四人所需要的时间分别是1,2,5,10分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,你如何设计一个方案,让用的时间最少。(17分钟)

这个问题实际上可以抽象为更一般的问题:N个人过桥,每人需要的时间是t[i],过桥规则不变,求所有人过桥所用的最短时间。

大多数题解是直接写,选两个最快的人,两个最慢的人,然后什么情况选什么方式过桥,然后递归。这样其实缺少理论上的严谨性。很多人会问:为什么选这四个人啊?

好,下面我们就来严谨的分析一下。

首先,下面几句话是显然的:

1.每个人都需要过桥;

2.最慢的两个人过桥后永远不会回来;(因为不会有人需要他们帮着过桥,也不会需要他们送手电筒,当然默认N>=4以保证最慢和最快不重合)

3.最慢的两个人不能两个人独自过桥;(否则就违反了第二条,必须有一个人回来送手电筒)

好,有了上面三句话,我们很容易得到两个推论。

1.要考虑把N个人送过去的最优时间,只需要先考虑怎么把最慢的两个人先送过去的最优时间。(类似于动态规划中的无后效性);

2.既然最慢的两个人不能独自过桥,那必须需要别人的帮助。那么需要谁的帮助呢?显然是最快的人的帮助。最快的几个人呢?讨论呗。(但是可以证明最多不超过两个人,因为假设有第三个人,任何一步他的帮助都没有什么作用)

这样,我们就已经知道为什么要选出这四个人了。现在来分析最优方案。

假设,t[1]~t[N] 是从小到大排好序的。设 A=t[1],B=t[2],C=t[N-1],D=t[N].

现在开始讨论:

1.如果C,D需要一个人的帮助过桥。那么最好的方案肯定是A把C送过去,A回来,A把D送过去,A回来。(A必须要回来,因为这边至少还有个B吧~)

T1=C+A+D+A

2.如果C,D需要两个人的帮助过桥。那么最好的方案肯定是A把B送过去,A回来,C和D过去,B回来。(B必须要回来,因为这边至少还有个A吧~)

T2=B+A+D+B

所以,只需要比较T1和T2的大小就可以确定选择哪一个方案。由公式,显然只需要比较A+C和2*B的大小。

而且,这两个方案的初始状态和终止状态都是一样的,而且选择之后的效果都是,左边的人少了两个。

那么问题就自然的转化为了N-2个人的过桥问题。就是递归的思想。

下面分析一下边界。

如果有三个人A,B,C(由小到大)。显然是用A送C,A回来,A送B。时间T=A+B+C。

如果有两个人。时间就是最大的时间。

一个人。时间就是这个人的时间。

算法详解就到这里。代码可以从网上就可以搜到,可以看一下是不是能看懂了呢?

时间: 2024-10-29 19:05:41

手电筒过桥问题详解的相关文章

南阳nyoj586疯牛 和nyoj619详解总结

这里先看nyoj619青蛙过桥,这样便于理解这两道题的共同点:最大值中的最小值, 题意:有一条河长L,中间有 n 块石头,青蛙最多可以跳 m 次,问题是:要保证青蛙能跳过去,那么它至少能一下跳多远,才能在m次范围内跳过去: 最大值中的最小值:这里要保证m次能跳过去,那么在这个过程中就会有很多种方法能在m次之内跳过去,那么,每一个方法中,我们就会有一个最大的跳跃距离! 比如:L=20,n=1:m=2:石头的位置是5 那么方法有:1.一次就跳过去,2.借助中间的石头,两次跳过去:那么在方法一中的最大

led指示灯电路图大全(八款led指示灯电路设计原理图详解)

led指示灯电路图大全(八款led指示灯电路设计原理图详解) led指示灯电路图(一) 图1所示电路中只有两个元件,R选用1/6--1/8W碳膜电阻或金属膜电阻,阻值在1--300K之间. Ne为氖泡,也选取用普通日光灯启辉器中的氖泡,若想用体积小且在60V左右即能启辉的氖灯泡,其型号为NNH-616型,电阻R选用270K的1/6W金属膜电阻.led指示灯电路: led指示灯电路图(二) 采用变压器将高压变为低压,并进行整流滤波,以便输出稳定的低压直流电.开关恒流源又分隔离式电源和非隔离式电源,

lspci详解分析

lspci详解分析 一.PCI简介 PCI是一种外设总线规范.我们先来看一下什么是总线:总线是一种传输信号的路径或信道.典型情况是,总线是连接于一个或多个导体的电气连线,总 线上连接的所有设备可在同一时间收到所有的传输内容.总线由电气接口和编程接口组成.本文讨论Linux 下的设备驱动,所以,重点关注编程接口. PCI是Peripheral Component Interconnect(外围设备互联)的简称,是普遍使用在桌面及更大型的计算机上的外 设总线.PCI架构被设计为ISA标准的替代品,它

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

MariaDB(MySQL)创建、删除、选择及数据类型使用详解

一.MariaDB简介(MySQL简介略过) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品.在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB. MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL A

HttpServletResponse和HttpServletRequest详解

HttpServletResponse,HttpServletRequest详解 1.相关的接口 HttpServletRequest HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletRequest接口可以获取由客户端传送的名称,也可以获取产生请求并且接收请求的服务器端主机名及IP地址,还可以获取客户端正在使用的通信协议等信息.下表是接口HttpServletRequest的常用方法. 说明:HttpServ

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

.NET深入解析LINQ框架(五:IQueryable、IQueryProvider接口详解)

阅读目录: 1.环路执行对象模型.碎片化执行模型(假递归式调用) 2.N层对象执行模型(纵横向对比链式扩展方法) 3.LINQ查询表达式和链式查询方法其实都是空壳子 4.详细的对象结构图(对象的执行原理) 5.IQueryable<T>与IQueryProvider一对一的关系能否改成一对多的关系 6.完整的自定义查询 1]. 环路执行对象模型.碎片化执行模型(假递归式调用) 这个主题扯的可能有点远,但是它关系着整个LINQ框架的设计结构,至少在我还没有搞懂LINQ的本意之前,在我脑海里一直频