本质:每步只选择当前最优解
贪心:不记录历史状态,只关心当前状态;动态规划:需要记录历史状态,在将来会被用到。
1.问题描述(过河问题)
在漆黑的夜里,甲乙丙丁共四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥的。不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,四人所需要的时间分别是1、2、5、8分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题:如何设计一个方案,让这四人尽快过桥。
解题思路:
假定四个人过河时间是T1,T2,T3,T4
且T1<T2<T3<T4
,如何选择过桥方案。
第一种过河方法的总时间为:T2+T1+T3+T1+T4
第二种过河方法的总时间为:T2+T1+T4+T2+T2
这两次方案的差异:次快的人要不要也传递一次手电筒。
结论:根据二者之差为:(T1+T3)-2T2
,选择过河方式
一般情况:
现在我们把这个问题推广:如果有N(N大于等于4)个旅行者,假设他们有各自所需的过桥时间有快有慢,各不相同。在只有一只手电筒的情况下,要过上述的一条桥,怎样才能找到最快的过桥方案?
现在我们假定,N个人单独过桥的时间分别是T1,T2,T3,……,Tn,且满足T1<T2<T3<…… <Tn。
经过分析,要满足最快过桥,合理的安排包括以下几点:
1)让最快的送手电筒的次数尽可能多些。
2)某些方案中,次快的也送电筒也可能会电筒。
3)让慢的过桥次数尽可能少些;
4)最快的两个先过桥,以保证此二人是能来回送电筒的人;
借助上述结论,来逐步分析多人情形。
当N=5人时,第一次先T1、T2两人过桥,T1把电筒送回,没过桥的又变成了T1、T3、T4、T5的4人情形。这个时候,需要比较T1+T4与2T3的大小吗?
第一种方案,还是选择T1来回送电筒,过桥总时间:为T2+T3+T1+T4+T1+T5
第二种方案,让慢的一起走,但因为送回电筒的不是T3,而是更快一点的T2,总过桥时间:T2+T5+T2+T3+T1+T2。
两种方案两者之差为T1+T4-2T2
,这里与T3没有关系。
当N=6人时,第一次先T1、T2两人过桥,T1把电筒送回,没过桥的又变成了T1、T3、T4、T5、T6 的5人情形。按照刚才的分析,要比较T1+T5-2T2的大小。
以此类推,两种方案的差异,只与最快的人、次快的人和次慢的人的单独过桥时间有关,而与其他人的快慢无关。
例题:
题目描述:
有n个人过河,但是河边只有一艘船;船每次最多坐三个人,每个人单独坐船过河的时间为a[i],两个人或者三个人一起坐船时,过河时间为他们所有人中最长的过河时间;为安全起见,要求每次至少有俩个人才能过河。问最短需要多少时间,才能把所有人送过河。
解题思路
贪心算法:
- 两个人或三个人取时间最长的
- 四个人先最短的三个先过,前两个回来,带最后一个
- 4人以上,有两种情况时间最短:
1)最短的两个带最长的,再回来带次最长的,依次带完
2)最短的两个带第三短的,最短的两个回来,由最短的带最长的两个过去,第一短和第三短回来。这样每次都将最长的两个送到对岸。
代码如下:
def min_time(a,n):
a.sort()
min_val=0
while n>=7:
tmp=a[2]+a[1]+a[3]+a[1]+a[n-1]+a[3]
min_val+=tmp
n-=3
if n>4 and n<=6:
tmp=min((a[n-1]+a[1]+a[n-2]+a[2]),(a[2]+a[1]+a[n-1]+a[2]))
min_val+=tmp
n-=2
if n==2 or n==3:
min_val+=a[n-1]
if n==4:
min_val+=a[2]+a[1]+a[3]
return min_val
122. 买卖股票的最佳时机 II
给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。
在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
profit = 0
for i in range(1, len(prices)):
tmp = prices[i] - prices[i - 1]
if tmp > 0: profit += tmp
return profit