小船过河问题解析(过度解析)

一开始输入一个数组a和一个数i(i代表人数) 

然后用冒泡排序从小到大进行排列,存放在数组a中(按照从小到大的顺序进行排列的目的是为了两种解决方案的实行)

dp[i]中存放的数据代表的意思就是当有i个人过河时,所需的最短时间

由于题目要求是当两个人同时乘船的时候 乘船时间是由时间长的人决定的 而返回路上只有一个人,因此乘船时间是由这个乘船的人决定的。

题目说了问题遵循两个原则:减少浪费(使得两个人所需时间差值尽可能小)和减少等待(船回去的时间尽可能小)

首先要明白该问题的最终结果是把所有人从这个岸通过船运往对岸,然后回来的时候还需要一个人回来,类似于搬运问题

这两个原则的意思是:

减少浪费:由于两人同时乘船时候去的时候,乘船时间是由时间长的人决定的,和所需时间短的那个无关,因此关键点在于: 现在还有三人没有运过去,三人所需时间分别为3h,6h,9h 接下来要运往两个去对岸,有三种选择(3,6)(3,9),(6,9),他们所需时间分别为6,9,9 其实这三种方案运输的时候(指的是两个人同时在船的时候肯定是必须有一次9的 因为3无论和谁组队都不起决定作用) 第一种方案运完3,6以后还需要再来一趟运9,并无差别 造成三种方案不同的是回来的时候,是谁单独回来 这时候咱们观察(3,9)和(6,9)两组数据

这里需要对比时需要分为两种情况 :

(1)对岸没有花费时间比剩下这三人更短的人 :

(3,9): 一开始运送3,9的时候 路上花费时间是9起作用因此去的时候花费9h,然后回来的时候需要一个人回来,肯定会选择一个时间短的回来那就是3,因此目前为止我们在路上花费的时间为9+3=12 当3回到对岸后,和6一起乘船 路上花费时间6>3因此时间自然是由6决定 因此总时间为9+3+6=18

(6,9):接下来考虑6和9,一开始运送6,9的时候 路上花费时间是9起作用因此去的时候花费9h,然后回来的时候需要一个人回来,肯定会选择一个时间短的回来那就是6,因此目前为止我们在路上花费的时间为9+6=15 当6回到对岸后,和3一起乘船 路上花费时间6>3因此时间自然是由6决定 因此时间为9+6+6=21

(2)假设对岸存在花费时间比剩下这三人更短的人,假设所需时间为1h :

(3,9): 一开始运送3,9的时候 路上花费时间是9起作用因此去的时候花费9h,然后回来的时候需要一个人回来,肯定会选择一个时间短的回来那就是1(早已到达对岸的),因此目前为止我们在路上花费的时间为9+1=10 当1回到对岸后,和6一起乘船 路上花费时间6>1因此时间自然是由6决定 因此总时间为10+6=16

(6,9):接下来考虑6和9,一开始运送6,9的时候 路上花费时间是9起作用因此去的时候花费9h,然后回来的时候需要一个人回来,肯定会选择一个时间短的回来那就是1,因此目前为止我们在路上花费的时间为9+1=10 当1回到对岸后,和3一起乘船 路上花费时间3>1因此时间自然是由3决定 因此时间为10+3=13

观察上述在减少浪费为目标的前提下两组值的四种情况比较大小 13<16<18<21

由此可以看到在假设对岸存在花费时间比剩下这三人更短的人的情况下,首次运送(6,9)所需时间更短,也就是题目里面所提到的减少浪费原则:(使得两个人所需时间差值尽可能小) ,但是这种情况下有一个前提那就是对岸有所需时间更短的人,因此第一步我们就要把数组中所需时间最短的两个人运送过去(后面减少浪费公式中也证实了第一步就是要先运送两个所需时间最短的人)。

减少等待原则:这个我的理解是这样的:因为我们的目的就是把所有人运送到对面,而两人同时乘船的时候正在完成这个目的,我们可以称两个人同时乘船的时候为等待时间。但当一个人开船返回的时候,他到达目的地之后不会完成运输人的工作,还没运输的人仍然不变,因此返回路上的时间称为等待时间(等待时间也可以称为是那些还没有被运输的人正在等待的时间)

因此我们该考虑的是如何去节省这个等待时间,也就是让回来的时候那个人所需的时间尽可能的短,很显然那就是每次让所需时间最短的那个人(这里让他名字为1)回来呗 也就是说每次两人同时乘船的时候也都要带上1,说白了在这里1起到的就是“搬运工”作用,依次搬运完。

因此转移状态方程为dp[i]=min(dp[i-1]+a[i]+a[1],dp[i-2]+a[2]+a[1]+a[i]+a[2])

首先数组a代表的时间一开始经过排序已经变为从小到大的顺序了 我们从最后一个依次开始考虑

至于状态转移方程的解释是这样的:由于每一次我们可选择的方案都是两种:“减少等待”和“减少浪费”两种,至于选择哪一步,就是比较哪一步最优,即这一步花费时间最短,因此我们取二者最小值。

dp[i-1]+a[i]+a[1]对应的是减少等待原则,代表的意思是从i个人开始考虑,去的时候第i个人和第1个人同时乘船,花费时间肯定为i,回来的时候让1回来,这样花费的时间就为a[i]+a[1],1回来以后现在问题变为i已经到岸了,1也回来了,我们只需剩余i-1人就可以了 因此式子为dp[i-1]+a[i]+a[1]。

dp[i-2]+a[2]+a[1]+a[i]+a[2]对应的是减少剩余原则,我们上面列举了四种情况,发现在对面有所需时间更短的人的时候,把一个所需时间最长和与他时间间隔最近的运往过去所需时间最短 因此第一步就要运送两个人时间最短的过去(这里为什么运送两个时间最短的过去,假如运送一个时间最短和最长不行吗,你好好看看如果这样的话是不是成了减少等待原则了),时间最短的两个就是1和2,然后去的时候2起决定性因素,因此时间为a[2],然后由1返回,因此时间为a[1],这样我们再把时间最长的和与他时间间隔最近的运往过去,即i和i-1,路上花费时间为a[i],目前为止花费的时间为a[2]+a[1]+a[i],这次我们是一下运送了两个最大的,现在对岸有2,i-1,i 因此回来的时候让2回来,路上花费时间为a[2] ,因此目前为止花费的时间为a[2]+a[2]+a[1]+a[i],并且目前状态是我们已经把i-1和i运送到对岸了,1和2也回到原来的岸边了,接下来只需考虑剩余i-2个人的情况就好了,剩余i-2人的情况表示为dp[i-2]。因此式子为dp[i-2]+a[2]+a[1]+a[i]+a[2]。

通过比较这两个式子所得大小做出选择之后然后再继续考虑剩余i-1或i-2个人的问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
贪心算法可以用来解决小船问题。根据题意,我们找到最快的过时间。根据引用中的描述,最优选择是先将所有人过所需的时间按照升序排序。然后我们可以考虑以下两种情况: 1. 最快的和次快的过,然后最快的将船划回来;次慢的和最慢的过,然后次快的将船划回来。这种情况的总时间为t + 2t + t[n-1。 2. 最快的和最慢的过,然后最快的将船划回来;最快的和次慢的过,然后最快的将船划回来。这种情况的总时间为2t + t[n-2 + t[n-1。 通过比较这两种情况的总时间,我们可以选择其中较小的时间作为最快的过时间。这样,我们就可以使用贪心算法解决小船问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [贪心算法——小船](https://blog.csdn.net/yangqiang1997/article/details/110232659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [贪心算法:小船问题](https://blog.csdn.net/dengmeiqing1378/article/details/102417708)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [JS基于贪心算法解决背包问题示例](https://download.csdn.net/download/weixin_38627213/13194957)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值