【四】《能力自检题单》——0217

目录

一、P5127 三带一(分类讨论)

对比总结

二、P5888 摆玩具(贪心、排序)

 三、P5130 健身【算法赛】(动态规划)


一、P5127 三带一(分类讨论)

小蓝和小桥玩斗地主,小蓝只剩四张牌了,他想知道是否是“三带一”牌型。

所谓“三带一”牌型,即四张手牌中,有三张牌一样,另外一张不与其他牌相同,换种说法,四张手牌经过重新排列后,可以组成 AAAB 型。

 1.三带一 - 蓝桥云课https://www.lanqiao.cn/problems/5127/learning/?problem_list_id=27&page=1

蓝桥杯python语言基础(2)——选择结构-CSDN博客https://blog.csdn.net/m0_73631172/article/details/145213659

# 输入
T=int(input())
for i in range(T):
    T_list=input()

# 分类讨论
    count={}
    for i in T_list:
        if i in count:
            count[i]+=1
        else:
            count[i]=1
    flag=0
    for j in count:
        if count[j]==3:
            flag=1

    if flag==1:
        print("Yes")
    else:
        print("No")
# 输入处理
T = int(input())
for _ in range(T):
    T_list = input().strip()

    count = {}  # 初始化统计字典
    for i in T_list:
        if i in count:
            count[i] += 1
        else:
            count[i] = 1
    # 判断是否为“三带一”牌型
    if 3 in count.values():
    #if 3 in count.values() and 1 in count.values():
        print("Yes")
    else:
        print("No")
from collections import Counter

# 输入处理
T = int(input())  # 读取轮数
for _ in range(T):
    cards = input().strip()  # 读取每轮的手牌
    count = Counter(cards)  # 统计每张牌的出现次数
    # 判断是否为“三带一”牌型
    print("Yes" if sorted(count.values()) == [1, 3] else "No")

对比总结

特性第一段代码第二段代码第三段代码
统计方式手动统计手动统计使用 Counter
判断逻辑仅判断是否存在字符出现3次判断是否存在字符出现3次判断是否同时存在字符出现3次和1次
代码简洁性较复杂较复杂简洁
适用性仅适用于简单判断仅适用于简单判断适用于准确判断“三带一”牌型

二、P5888 摆玩具(贪心、排序)

小蓝是一个热爱收集玩具的小伙子,他拥有 n 个不同的玩具。

这天,他把 n 个玩具按照高度顺序从矮到高摆放在了窗台上,然后,他希望将这些玩具分成 k 个段,使得所有分段的极差之和尽可能小。

3.摆玩具 - 蓝桥云课https://www.lanqiao.cn/problems/5888/learning/?problem_list_id=27&page=1 蓝桥杯python基础算法(2-2)——基础算法(G)——离散化、贪心_蓝桥杯贪心python讲解-CSDN博客https://blog.csdn.net/m0_73631172/article/details/145399671

# 输入
n,k=map(int,input().split())
n_list=list(map(int,input().split()))

# [贪心]
# 不断选择最大的差值作为分界点

#计算相邻差值
diff=[]
for i in range(1,n):
    diff.append(n_list[i]-n_list[i-1])

# [排序]
diff.sort(reverse=True)

# 将相邻最大差值的分段,减去最大的k个,剩下的就是最小极差
for i in range(k-1):    #k-1
    diff.pop(0)

# 求的是极小差值的和
print(sum(diff))
# 输入
n,k=map(int,input().split())
n_list=list(map(int,input().split()))

# [贪心]
# 计算所有差值的和减去其中k的最大差值的和就是最小差值的和

#计算相邻差值
diff=[]
for i in range(1,n):
    diff+=[n_list[i]-n_list[i-1]]

# [排序]
total=n_list[-1]-n_list[0]
diff.sort(reverse=True)
for i in range(k-1):
    total-=diff[i]

print(total)
# 输入   
n, k = map(int, input().split())
h = list(map(int, input().split()))

# 初始化DP数组
dp_prev = [h[i] - h[0] for i in range(n)]
dp_curr = [float('inf')] * n
# 动态规划求解
for j in range(1, k):  # 分段数
    for i in range(n):  # 元素数
        dp_curr[i] = float('inf')
        for m in range(j - 1, i):  # 分段点
            dp_curr[i] = min(dp_curr[i], dp_prev[m] + (h[i] - h[m]))
    # 更新dp_prev
    dp_prev, dp_curr = dp_curr, dp_prev

print(dp_prev[-1])
 
特性第一段代码(贪心)第二段代码(贪心改进)第三段代码(动态规划)
算法贪心贪心动态规划
时间复杂度​O(nlogn)​​O(nlogn)​​O(n2⋅k)​
适用性仅适用于特定情况仅适用于特定情况适用于任意情况
代码复杂度简单简单复杂

 三、P5130 健身【算法赛】(动态规划)

小蓝要去健身,他可以在接下来的 1∼n 天中选择一些日子去健身。

他有 m 个健身计划,对于第 i 个健身计划,需要连续的 2^ki​ 天,如果成功完成,可以获得健身增益 si​ ,如果中断,得不到任何增益。

同一个健身计划可以多次完成,也能多次获得健身增益,但是同一天不能同时进行两个或两个以上的健身计划。

但是他的日程表中有 q 天有其他安排,不能去健身,问如何安排健身计划,可以使得 n 天的健身增益和最大。

 4.健身【算法赛】 - 蓝桥云课https://www.lanqiao.cn/problems/5130/learning/?problem_list_id=27&page=1

 蓝桥杯python笔记(4-1):动态规划基础——线性DP和二维DP_第一行包含两个数字,n 和 m ( 1 ≤ ≤ 1 0 6 , 2 ≤ ≤ 1 0 3 1≤-CSDN博客https://blog.csdn.net/m0_73631172/article/details/145548637

# 输入
n, m, q = map(int, input().split())
ti = [0] + list(map(int, input().split())) + [n + 1]
kisi = []
for _ in range(m):
    k, s = map(int, input().split())
    kisi.append((2**k, s))

# 分段处理:每段连续可用日期的长度
segments = [ti[i] - ti[i - 1] - 1 for i in range(1, len(ti))]

# 动态规划
dp = [[0] * (m + 1) for _ in range(max(segments) + 1)]
for i in range(1, len(dp)):
    for j in range(m):
        length, s = kisi[j]
        if i >= length:
            dp[i][j] = max(dp[i - length][-1] + s, dp[i - 1][-1])
        else:
            dp[i][j] = dp[i - 1][-1]
    dp[i][-1] = max(dp[i])

# 计算结果:将所有段的增益相加,得到最终的最大增益
result = 0
for seg in segments:
    result += max(dp[seg])

print(result)
  • 采用了分段处理的方法,将日期范围分成多个段,每个段之间是不可用日期。
  • 使用了一个二维DP数组来处理每个段的最大收益。

# 输入
n,m,q=map(int,input().split())
ti=list(map(int,input().split()))
kisi=[]
for i in range(m):
    kisi.append(tuple(map(int,input().split())))

# 动态规划
dp=[0]*(n+1)
for i in range(1,n+1):
    if i in ti:
        dp[i]=dp[i-1]
    else:
        dp[i]=dp[i-1]
        for k,s in kisi:
            length=2**k
            if i>=length and all(j not in ti for j in range(i-length+1,i+1)):
                dp[i]=max(dp[i],dp[i-length]+s)
print(dp[n])



# 输入
n,m,q=map(int,input().split())
ti=list(map(int,input().split()))
kisi=[]
for i in range(m):
    kisi.append(tuple(map(int,input().split())))
# 标记不可用日期
busy=[False]*(n+1)
for i in ti:
    busy[i]=True

# 动态规划
dp=[0]*(n+1)
for i in range(1,n+1):
    if i in ti:
        dp[i]=dp[i-1]
    else:
        dp[i]=dp[i-1]
        for k,s in kisi:
            length=2**k
            if i>=length and not any(busy[i-length+1:i+1]):
                dp[i]=max(dp[i],dp[i-length]+s)
print(dp[n])



n, m, q = map(int, input().split())
ti = list(map(int, input().split()))
kisi = []
for _ in range(m):
    k, s = map(int, input().split())
    kisi.append((2**k, s))  # 直接存储 2^k

# 标记不可用日期
busy = set(ti)  # 使用集合加速查找

# 动态规划
dp = [0] * (n + 1)
for i in range(1, n + 1):
    if i in busy:  # 如果第 i 天不可用
        dp[i] = dp[i - 1]
    else:
        dp[i] = dp[i - 1]  # 不进行任何健身计划
        for length, s in kisi:
            if i >= length and all(j not in busy for j in range(i - length + 1, i + 1)):
                dp[i] = max(dp[i], dp[i - length] + s)

print(dp[n])

如果不分段处理,可以通过直接对整个日期范围进行动态规划来计算最大健身增益。这种方法在不可用日期较少时是可行的,但在不可用日期较多时,效率较低。

改进:

n, m, q = map(int, input().split())   
ti = set(map(int, input().split()))   
kisi = []   
for i in range(m):
    k, s = map(int, input().split())
    kisi.append((2 ** k, s))
   
# 动态规划   
dp = [0] * (n + 1)   
for i in range(1, n + 1):
    if i in ti:
        dp[i] = dp[i - 1]
    else:
        dp[i] = dp[i - 1]
        for length, s in kisi:
            if i >= length and all(j not in ti for j in range(i - length + 1, i + 1)):
                dp[i] = max(dp[i], dp[i - length] + s)   
print(dp[n])

能通过全部测试用例检测,但是不显示通过率,存在未知问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值