贪心算法python

找零钱问题

假设只有 1 分、 2 分、五分、 1 角、二角、 五角、 1元的硬币。在超市结账 时,如果 需要找零钱, 收银员希望将最少的硬币数找给顾客。那么,给定 需要找的零钱数目,如何求得最少的硬币数呢?

d=[0.01, 0.02, 0.05, 0.1,  0.2,  0.5,1.0]#7种
s=0
shu=list(map(int,input("请输入7种零钱的数量:").split(" ")))
print(shu)

for i in range(7):
    s+=d[i]*shu[i]

sum=float(input("需要找的零钱:"))

i=6
while i>=0:
    if sum>=d[i]:        
        num=min(sum//d[i],shu[i])#题目要求数量最少
        sum -=num * d[i]
        print("用了%d个%f元硬币"%(num , d[i]))
    i-=1
    

最优装载问题

问题描述:

有一天海盗们截获了一艘装满各种各样古董的货船,每一件都价值连城,一旦打碎就是去了价值, 海盗船载重量为C,每件固定的重量为wi,海盗们该如何尽可能装载最多数量的古董呢?
古董重量清单:
重量W[i] 4 ,10,7 ,11, 3, 5, 14, 2
算法设计:

  1. 船载重量固定为C,只要每次选择重量最小的古董,直到不能再装为止,这样装载的古董数量最大,这就是贪心策略;
  2. 把古董按重量从小到大排序,根据策略选出尽可能多的古董。
def max_ans(antique):
    anti_sort=sorted(antique)
    c=int(input("请输入海盗船能装载的最大容量"))
    ans,tmp=0,0
    ship=[]
    for a in anti_sort:
        tmp+=a
        if tmp <=c:
            ans+=1
            ship.append(a)
    print("装载古董的数量:",ans)
    print("装载的古董",ship)

antique=[2,10,7,11,3,5,14,2]
max_ans(antique)

毛驴运载能力

问题描述:
假设山洞中有n种宝物,每种宝物有一定重量w和相应的价值v,毛驴运载能力 一种宝物只能拿一样,宝物可分割。怎样才能使毛驴运走宝物的价值最大呢?
问题分析:
可以尝试三种贪心策略:
每次挑选价值最大的装东西入背包;
每次挑选最重的东西;
每次选取单位重量价值最大的东西。
算法设计:

  1. 计算出每件宝物的性价比,按照从高到低排序;
  2. 根据贪心策略,按性价比从大到小选取宝物,直到达到毛驴的运载能力。每次选择宝物后判断是否小于m,如果不小于则取走宝物的一部分,程序结束。
datas = [
    [4, 3], [2, 8], [9, 18], [5, 6],
    [5, 8], [8, 20], [5, 5], [4, 6],
    [5, 7], [5, 15]]
#第一列重量,第二列价值

donkey=30
get_price=0

for i in range(len(datas)):
    price=datas[i][1]/datas[i][0]#单位价值
    datas[i].append(price)
datas.sort(key=lambda data :data[2],reverse=True)#排序

for data in datas:#例如[4,3][重量,价值]
    if data[0]<=donkey:
        get_price +=data[1]
        donkey -=data[0]
    else:
        get_price +=data[2] *donkey#取走宝物的一部分
        break
print("总价值:",get_price)

求最大子数组之和问题

给定一个整数数组(数组元素有负有正),求其连续子数组之和的最大值。

s=[12,-4,32,-36,12,6,-6]#定义的数组
smax,ssum=0,0  #smax最大,ssum数字之和
for i in range(len(s)):
    ssum += s[i]
    if ssum<0:#有正数,最大就不可能是负的,换车头
        ssum=0 #新开始
    else:
        smax=max(ssum,smax)
print(smax)    

停靠加油站

一辆汽车加满油后可行驶n公里。旅途中有若 干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。 对于给定的n(n <= 5000)和k(k <= 1000)个加油站位置,编程计算最少加油次数。

n=100  #加满油可以走多远
k=5 #加油站个数
d=[50,80,39,60,40,32]#加油站间隔距离,默认不会大于n
num=0

i,sum=0,0
while i<=k:
    sum +=d[i]
    if sum>=n:#50+80>100,所以第一个加油站就得加油
        sum=d[i]
        num+=1
    i+=1
print(num)

最优合并问题

给定k个排好序的序列s1,s2,…,sk,用2路合并算法将这k个序列合并成一个序列。假设所采用的2路合并算法合并两个长度分别为m和n的序列需要m+n-1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需要的总比较次数最少。
测试用例: 4(序列数)
5 12 11 2(序列中的元素数)
输出: 78(最差情况) 52(最优情况)

分析:
“最差合并顺序:总是最长的两个先合并
最优合并顺序:总是最短的两个先合并 ”

n=4
ListLong=[5,12,11,2]
ListLong.sort(reverse = True)#从大到小排序
max=ListLong[0]+ListLong[1]#总是前两个大的先合并
total=max-1
for i in range(2,n):
    max +=ListLong[i]
    total +=max-1
print('最差',total)

ListLong2=[5,12,11,2]
ListLong2.sort()#从小到大排序
min=ListLong2[0]+ListLong2[1]#总是前两个小的合并
total=min-1
for i in range(2,n):    
    min +=ListLong2[i]
    total +=min-1
print('最优',total)

'''
最差 78
最优 52
'''

翻硬币

题目描述:
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:oo*oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:
输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000
输出格式
一个整数,表示最小操作步数。
思路:
找两个字符串不相同的位置,记录下所有不相同的下标,一对一对的求其下标的差值,最后再累加即可(题目间接告诉我们,不同的位置的个数一定是偶数)
举个例子:

*o**o***o*** 
*o***o**o*** 
#sa,sb=map(str,input().split(' '))
sa=list(input())
sb=list(input())
s=[]
for i in range(len(sa)):
    if sa[i]!=sb[i]:
        s.append(i)
sum=0
for i in range(len(s)-1,0,-2):
    sum +=s[i]-s[i-1]
print(sum)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值