笔试刷题 | 贪心算法
定义
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
个人疑惑
这句话能否在现实生活中使用?
因为生活中常常接触的道理是不能短视,要有大局观,牵一发而动全身,不能为了一点蝇头小利而失去自我。
而贪心算法都是基于当前做一个最优选择,以及它的前提是当前状态不影响以后状态,这个前提怎么能做到呢?因为,我们生活中的得失都是之前做出的决断共同造就的呀。
不过,贪心算法并不一定能得到全局最优解,这是肯定的。
#! /usr/bin/env python# -*-coding:utf-8-*-"""Author: ChileWangCreated at 2020/03/20 15:59Question:贪心算法常用于处理一维度问题,所得的解并不一定是最优解贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题 。"""import randomdef horse_competition():n = int(input("输入马匹数目:"))tj = [] # 田忌马匹速度qw = [] # 齐王马匹速度reward = 0for i in range(0, n):tj.append(random.randint(0, 100))qw.append(random.randint(0, 100))# 从小到大排序tj = sorted(tj)qw = sorted(qw)print(tj)print(qw)while len(tj):if tj[0] > qw[0]: # 田忌最慢的马比齐王最慢的马快reward += 1del tj[0], qw[0]elif tj[0] == qw[0]: # 田忌最慢马和齐王最慢的马一样del tj[0], qw[0]else: # 田忌最慢的马比齐王最慢的马垃圾reward -= 1del tj[0], qw[-1] # 删除田忌最慢的马和齐王最快的马print(reward)def candy_demand():"""题目:已知一些孩子和一些糖果,每个孩子有需求因子g,每个糖果有大小s,当某个糖果的大小s>=某个孩子的需求因子g时,代表该糖果可以满足该孩子,求使用这些糖果,最多能满足多少孩子(注意,某个孩子最多只能用1个糖果满足):return:"""g = [5, 10, 2, 9, 15, 9]s = [6, 1, 20, 3, 8]g = sorted(g)s = sorted(s)print(g)print(s)child = 0candy = 0while child < len(g) and candy < len(s):if g[child] <= s[candy]:child += 1candy += 1print(child)def get_max_len():"""给定一个整数序列,返回作为摆动序列的最长子序列的长度。通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。:return:"""arr = [1, 17, 5, 10, 13, 15, 10, 5, 16, 8]arr = [1,2,3,4,5,6,7,8,9]arr = [1,7,4,9,2,5]if len(arr) < 2:print(len(arr))else:# Begin = 0, Up = 1, Down = 2state = 0max_len = 1for i in range(1, len(arr)):if state == 0:if arr[i - 1] < arr[i]:state = 1max_len += 1elif arr[i - 1] > arr[i]:state = 2max_len += 1elif state == 1:if arr[i - 1] > arr[i]:state = 2max_len += 1elif state == 2:if arr[i - 1] < arr[i]:state = 1max_len += 1print(max_len)def remove_digits():"""题目:已知一个使用字符串表示非负整数num,将num中的k个数字移除,求移除k个数字后,可以获得的最小的可能的新数字(num不会以0开头,num长度小于10002)例如:输入:num = “1432219”,k=3在去掉3个数字后得到的很多可能里,如1432,4322,2219,1219;去掉数字4、3、2、得到的1219最小:return:"""a = "1430219"k = 2stack = []for num in a:number = int(num)while stack and k and int(stack[-1]) > number:stack.pop()k -= 1stack.append(num)while k and stack:stack.pop()k -= 1print(stack)if not stack:print("0")else:print("".join(stack))def marry_candy_value():"""4.圣诞节发糖果圣诞节来临了,在城市A中,圣诞老人准备分发糖果。现在有多箱不同的糖果,每一种糖果都有自己的价值和重量。每箱糖果都可以拆分成任意散装组合带走。圣诞老人的驯鹿最多只能承受一定重量的糖果。请问圣诞老人最多能带走多大价值的糖果。输入数据:输入的第一行由两个部分组成,分别为糖果箱数正整数n(1<=n<=100),驯鹿能承受的最大重量正整数w(0<w<10000);其余n行每行对应一箱糖果,由两部分正整数v和w组成,分别为一箱糖果的价值和重量。输出要求:输出圣诞老人能带走的糖果的最大总价值,保留一位小数,输出为一行。输出样例:4 15100 4412 8266 7591 2输出样例:1193.0:return:"""a = 4 # 箱数max_load = 15 # 麋鹿最大的载重量value = [100, 412, 266, 591] # 每种糖果的总价值load = [4, 8, 7, 2] # 每种糖果的总量value_per_load = [] # 单位重量价值list_load_state = []for i in range(len(value)):avg = round(value[i]/load[i], 1) # 单位重量的价格value_per_load.append(avg)list_load_state.append([load[i], avg, False]) # [每种糖果对应的总重量, 单位重量的价格, 是否被取走]value_per_load.sort(reverse=True) # 从大到小排序all_sum = [0, 0] # 取走的总重量, 取走前的重量备份sum_value = 0 # 总价值flag = 0 # 是否超过马车总载重for i in range(len(value_per_load)):for j in range(len(list_load_state)):if flag == 0: # 重量未超过,标志为0if value_per_load[i] == list_load_state[j][1] and (not list_load_state[j][2]):all_sum[1] = all_sum[0] # 备份取走前的总量all_sum[0] += list_load_state[j][0]current_get_load = list_load_state[j][0]if all_sum[0] > max_load: # 大于总载重,循环迭代减少单位重量flag = 1 # 超出马车最大承重梁, flag=1while True:z = all_sum[1] + current_get_load # 使用备份重量判断是否超过max_loadif z <= max_load:breakcurrent_get_load -= 1all_sum[0] = all_sum[1] # 回复原始的备份载重量all_sum[0] += current_get_load # 真实拿走的重量sum_value += value_per_load[i] * current_get_loadlist_load_state[j][2] = True # 取走标志else:breakprint('Value:', sum_value)def greedy():"""一辆汽车加满油后可行驶n公里。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。对于给定的n(n <= 5000)和k(k <= 1000)个加油站位置,编程计算最少加油次数。:return:"""n = 100k = 5d = [50, 80, 39, 60, 40, 32]# 表示加油站之间的距离num = 0# 表示加油次数for i in range(k):if d[i] > n:print('no solution')# 如果距离中得到任何一个数值大于n 则无法计算returni, s = 0, 0# 利用s进行迭代while i <= k:s += d[i]if s >= n:# 当局部和大于n时, 则局部和更新为当前距离,表示加完油之后已经行驶的距离s = d[i]# 贪心意在令每一次加满油之后跑尽可能多的距离num += 1i += 1print(num)if __name__ == '__main__':candy_demand()get_max_len()remove_digits()marry_candy_value()greedy()
