蓝桥杯 调手表【第九届】【决赛】【B组】python dp

想说的话

大家好🌼🌼,我是 @愿此后再无WA,可以叫我小A,也可以叫我愿愿💡💡,一位阳光帅小伙,对算法领域比较感兴趣。如果我的文章对您有用,欢迎持续关注,我们一起进步!🎈🎈

很抱歉各位😪😪,现离蓝桥杯比赛不到一个月时间,我临时改变了计划,转为全心备战蓝桥,因为这个省一对我来说太重要了,也是我最后一次机会,我一定要拿到手📌📌,那么这样的话我在博客上花的时间就会少了很多,也将导致博客文章质量明显下降,在此我给大家说声抱歉💥💥


🌟🌟这些日子我真的很开心,博客上能遇到一群志同道合的兄弟姐妹真的很幸福,没有你们的支持与鼓励我早就坚持不下去了,因为有你们我才能走的更远☀️☀️熬过这段时期我一定会回来的,爱你们❤️❤️

调手表

在这里插入图片描述
在这里插入图片描述

吐槽

不容易啊,做这题需要用到DP或BFS,虽然大致的框架搭完了,但是总是小问题不断,调试了好久都没有AC,我发现这种题目真的很难调试,如果想一会想不出特例的话之后都不会想到的。一开始想的太简单了,没有考虑到在这里插入图片描述
于是我两三分钟就写出一个半成品
在这里插入图片描述
一提交发现能拿50分,3分钟能拿到这么多真的血赚。

话说回来,既然要取模,而且是能够循环的,那么可能会出现负数取模的情况,我特地把这知识点补了一下。

负数取模,假设-A mod(%) B 就它的余数就等于-1 x B + A.
在这里插入图片描述
我就讲一下-2 =-1x7+5,其中-2,-1,7是固定的,-1是负数取模的乘数因子,7是被模数,剩下的5就是通过这个等式得出来的,而5就是结果了。

思路

其实呢,python的索引支持负数,所以不需要对负数取模也能得出结果。

先理一下题目大意,就是求调每一分钟最少需要的最大次数。比如这个星球一小时有5分钟,那么可能需要调一分钟,两分钟,三分钟,四分钟才能对准时间,或者不调,而调这些分钟可以按+1键也能够按K键调,所以我们就要找其中需要的最少次数。

因此,这题有两个状态,一个是按+1键,一个是按+K键。对于每一分钟来说就是看是按+1键调还是按+k键调,取其中的最小值(最优子结构)。

首先初始化状态,先初始化全按+1键需要的次数,接着初始化全按K键需要的次数,最后选择其中的最小值。

初始化K键尤其重要也很容易错,需要对大于N的数取模。

dp[X] 表示按X分钟需要的最少次数。

代码

N,K=map(int,input().split())

# 初始化状态1,记录按+1键得到要调i分钟需要的次数
dp=[i for i in range(N)] 
#print(dp)


# 初始化状态2, 记录按i次K键得到各分钟需要次数的最小值,
for i in range(N):

    val = i * K % N  # 每次得到K的倍数,若大于N则取余

    dp[val] = min(i,dp[val])  # 该位置取全按K键和全按+1键的最小值
    
for i in range(1,N):  # 寻找最优子结构

    # 要么是通过上个数按+1键得到
    #要么按+K键得到,而这样得到算按一次所以要+1
    # 要么是本身,如果是本身说明该分钟是K的倍数,在初始化时已达最优
    # 取三者最小值
    dp[i]=min(dp[i-1]+1,dp[i-K]+1,dp[i])
  
print(max(dp))

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿此后再无WA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值