145
社区成员
发帖
与我相关
我的任务
分享贪心算法总是做出在当前看来是最好的选择。也就是说,贪心算法并不从整体最优上加以考虑,所做的选择只是在某种意义上的局部最优选择。当然,我们希望贪心算法得到的最终结果也是整体最优的。
贪心算法通过一系列选择来得到问题的解,所做的每个选择都是当前状态下局部最好选择,即贪心选择。这种启发式的策略并不总能奏效,但在许多情况下确能达到预期目的。贪心算法一般具有两个重要的性质:贪心选择性质和最优子结构性质。
1.贪心选择性质
贪心选择性质是指,所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。在动态规划算法中,每步所做的选择往往依赖于相关子问题的解。因而只有在解出相关子问题后,才能做出选择。而在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择。再去解做出这个选择后产生的相应的子问题。贪心算法所做的贪心选择可以依赖以往所做过的选择,但决不依赖将来所做的选择,也不依赖子问题的解。正是由于这种差别,动态规划算法通常以自底向上的方式解各子问题,贪心算法则通常以自顶向下的方式进行,以迭代的方式做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每步所做的贪心选择最终导致问题的整体最优解,通常可以用类似于证明活动安排问题的贪心选择性质时所采用的方法来证明。首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明,通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于,利用该问题的最优子结构性质。
2.最优子结构性质
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
0-1背包问题:在选择装入背包中的物品时,对每种物品i只有两种选择(装入或不装),不能将同一个物品装入多次,也不能只装入一个物品的一部分。因此,0-1背包问题为一个特殊的整数规划问题。
背包问题:与0-1背包不同的是,可以选择物品i的一部分,不一定要全放入。这两类问题都具有最优子结构性质。但背包问题可以用贪心算法求,而0-1背包问题不能用贪心算法求解。
对于0-1背包问题,贪心选择不能得到最优解是因为:这种情况下,不能保证背包装满,部分闲置的背包空间使每kg背包空间的价值降低了。而实际上,考虑0-1背包问题时,应该比较选择该物品和不选择该物品所导致的最终方案,再做比较。由此会导出很多相互重叠的子问题,这正是用动态规划求解的一个重要特征。
贪心算法与动态规划算法的异同:
共同点:贪心算法和动态规划算法都要求问题具有最优子结构性质
不同点:动态规划通常以递推方式求解各个子问题,某个子问题的解依赖于已知子问题的最优解在做出选择。贪心算法通常以一系列的局部贪心选择和求解,每个局部阶段,先做贪心选择,再解子问题。
题目:

代码如下:
# 最优合并问题
def Most(num):
num1 = num.copy()
# 将列表num1降序排列
num1.sort(reverse=True)
print(num1)
Times = 0 # 总的比较次数
times = 0 # 每两个序列的比较次数
for i in range(n - 2):
# 取序列长度最长的两个序列先进行比较
times = num1[0] + num1[1]
Times = Times + times - 1
# 删除已比较的序列
del num1[0]
del num1[0]
# 加入合并后的序列
num1.append(times)
num1.sort(reverse=True)
times = num1[0] + num1[1] - 1
Times = Times + times
return Times
def Least(num):
num2 = num.copy()
# 将列表num2升序排列
num2.sort()
print(num2)
Times = 0 # 总的比较次数
times = 0 # 每两个序列的比较次数
for i in range(n - 2):
# 取序列长度最短的两个序列先进行比较
times = num2[0] + num2[1]
Times = Times + times - 1
# 删除已比较的序列
del num2[0]
del num2[0]
# 加入合并后的序列
num2.append(times)
num2.sort()
times = num2[0] + num2[1] - 1
Times = Times + times
return Times
# 从文件中读出数据
file_readpath = '3_input.txt'
with open(file_readpath) as file:
txt = file.read()
txt = txt.split('\n')
# n代表数据的个数
n = eval(txt[0])
num = []
txt = txt[1].split()
for i in range(n):
num.append(eval(txt[i]))
# 输出结果用于验证
most = Most(num)
least = Least(num)
print("最多次数为:", most)
print("最少次数为:", least)
# 将结果存入文件output.txt
file_writepath = '3_output.txt'
file = open(file_writepath, "w")
file.write(str(most) + ' ' + str(least))
file.close()
输入文件如下:

控制台输出如下:
输出文件如下:

题目如下:
代码如下:
# n为堆数,k为一次处理多少,s是石头数据
def maxFare(n, k, s):
s.sort(reverse=True)
print(s)
maxFareNum = 0
onceAct = 0
while len(s) > 1:
for i in range(2):
onceAct += s[0]
maxFareNum += s[0]
s.pop(0)
s.append(onceAct)
onceAct = 0
s.sort(reverse=True)
print(maxFareNum)
return maxFareNum
def minFare(n, k, s):
s.sort()
minFareNum = 0
oneAct = 0
while len(s) > k:
for i in range(k):
oneAct += s[0]
minFareNum += s[0]
s.pop(0)
s.append(oneAct)
oneAct = 0
s.sort()
for i in range(len(s)):
minFareNum += s[0]
s.pop(0)
print(minFareNum)
return minFareNum
if __name__ == '__main__':
f = open('4_input.txt')
line = f.readline()
n, k = map(lambda x: int(x), line.split(' '))
if line:
line = f.readline()
line = line.split(' ')
s = list(map(lambda x: int(x), line))
with open('4_output.txt', 'w') as f:
f.write(str(maxFare(n, k, s.copy())) + ' ' + str(minFare(n, k, s)))
f.close()
输入文件如下:

控制台输出如下:

输出文件如下:
