蓝桥杯python编程每日刷题 day 12(2023)

小知识点:

该题中,有字母对应关系,可用ord(),如ord(“a“)= 98

题目:

给定一个仅含小写字母的字符串 s ,假设 s 的一个子序列 t 的第 i 个字符 对应了原字符串中的第 pi 个字符。我们定义 s 的一个松散子序列为:对于 i > 1 总是有 pi − pi−1 ≥ 2 。设一个子序列的价值为其包含的每个字符的价值之和 ( a ∼ z 分别为 1 ∼ 26 ) 。 

求 s 的松散子序列中的最大价值。 

(1)代码:

def get(c):
    return ord(c) - ord("a") + 1
x = input()
n = len(x)
dp = [[0,0] for i in range(n)]
dp[0][1] = get(x[0])
for i in range(1,n):
    dp[i][0] = max(dp[i-1][0],dp[i-1][1])
    dp[i][1] = dp[i-1][0] + get(x[i])
print(max(dp[-1][0],dp[-1][1]))

(2)解析:

  • 如果取第 i 个字符,那么根据松散子序列的定义(p_i - p_{i-1} >= 2),前一个字符必须不取。
    • 如果前一个字符被选中了,那么当前字符和前一个字符在原字符串中的位置差必须至少为 2。
    • 如果前一个字符也被选中了,那么它们的距离可能不满足 p_i - p_{i-1} >= 2 的条件。
  • 因此,取第 i 个字符时,前一个字符必须不取。
公式

dp[i][1]=dp[i−1][0]+value(s[i])

  • 如果不取第 i 个字符,那么当前的最大价值完全取决于前一个字符的状态。
  • 因为第 i 个字符没有被选中,所以前一个字符既可以取,也可以不取,这不会影响松散子序列的定义。
  • 我们需要选择前一个字符的两种状态(取或不取)中的最大值,作为当前不取第 i 个字符的最大价值。
公式

dp[i][0]=max(dp[i−1][0],dp[i−1][1])

3)注意事项:

这是一类有代表性的问题,具体可以参考Leetcode上的打家劫舍问题系列,将问题转换成:给定一个序列,要求不能选取相邻的元素,问能获得的最大价值是多少?此问题为典型的动态规划问题,第i项的值由第i-1项来决定

你可能感兴趣的:(蓝桥杯,python,算法)