蓝桥杯-动态规划

  1. 小明的背包1-1174
    方法一:
# 自下向上,先小问题再大问题,递推
N, C = map(int, input().split()) # 物品数量,背包体积
c = [0] # 每件物品的体积
w = [0] # 每件物品的价值
for i in range(N):
    a, b = map(int, input().split())
    c.append(a)
    w.append(b)
assert len(c) - 1 == N and len(w) - 1 == N
dp = [[0]*(C+1) for _ in range(N+1)]

for i in range(1, N+1):
    for j in range(C+1):
        if c[i] > j: # 装不下
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i-1][j], dp[i-1][j-c[i]]+w[i])

print(dp[N][C])

方法二:
好像超时了

# 自顶向下,先大问题再小问题,递归
N, C = map(int, input().split())
c = [0] # 每件物品的体积
w = [0] # 每件物品的价值
for i in range(N):
    a, b = map(int, input().split())
    c.append(a)
    w.append(b)
assert len(c) - 1 == N and len(w) - 1 == N
dp = [[0]*(C+1) for _ in range(N+1)]

def solve(i, j):
    global dp
    if dp[i][j] != 0:
        return dp[i][j]
    if i == 0:
        return 0
    if c[i] > j: # 装不下
        dp = solve(i-1, j)
    else:
        dp[i][j] = max(solve(i-1, j), solve(i-1, j-c[i])+w[i])
    return dp[i][j]

print(solve(N, C))
  1. 最长公共子序列-1189
N, M = map(int, input().split())  # 数组a和b的长度
a = [0] + list(map(int, input().split()))
b = [0] + list(map(int, input().split()))
m = max(N, M) + 1
dp = [[0]*m for _ in range(m)]
for i in range(1, N+1):
    for j in range(1, M+1):
        if a[i] != b[j]:
            dp[i][j] = max(dp[i-1][j], dp[i][j-1])
        else:
            dp[i][j] = dp[i-1][j-1] + 1

print(dp[N][M])
  1. 最长公共子序列-1054
    暴力法,在上一题的基础上使用全排列,如非填空题无法使用。
import itertools
s1 = input()[:-1]
s2 = input()[:-1]
a = [0] + list(s1)
b = [0] + list(s2)
N, M = len(a)-1, len(b)-1
m = max(N, M) + 1
dp = [[0]*m for _ in range(m)]
for i in range(1, N+1):
    for j in range(1, M+1):
        if a[i] != b[j]:
            dp[i][j] = max(dp[i-1][j], dp[i][j-1])
        else:
            dp[i][j] = dp[i-1][j-1] + 1

print(dp[N][M])

p = list(itertools.combinations(s1, dp[N][M]))
q = list(itertools.combinations(s2, dp[N][M]))

s = 0
for i in p:
    for j in q:
        if i == j:
            s += 1
    
print(s)
  1. 编辑距离
    最后几个测试用例会超时
A = input()
B = input()

a, b = len(A), len(B)

dp = [[0]*(b+1) for _ in range(a+1)]
#A为空:需要增加i个字符使A转化为B
for i in range(1, len(A)+1):
    dp[i][0] = i
#B为空:需要减少i个字符使A转化为B
for i in range(1, len(B)+1):
    dp[0][i] = i

for i in range(1, a+1):
    for j in range(1, b+1):
        if (A[i-1] == B[j-1]):
            dp[i][j] = dp[i-1][j-1] # 不变
        else: # 删除,插入,修改
            dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1)

print(dp[a][b])
  1. 小明的背包2-1175(完全背包)
N, V = map(int, input().split()) # 物品数量,背包容量
w = [0] # 体积
v = [0] # 价值
for i in range(N):
    a, b = map(int, input().split())
    w.append(a)
    v.append(b)
dp = [[0]*(V+1) for _ in range(N+1)]
for i in range(1, N+1):
    for j in range(1, V+1):
        if w[i] > j: # 装不下
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i][j-w[i]]+v[i], dp[i-1][j])
            # 和非完全背包仅有的区别: dp[i][j-w[i]]+v[i]

print(dp[N][V])
  1. 采药-563
# 背包问题
T, M = map(int, input().split()) # 总时间,数目
t = [0]  # 采摘某株草药的时间
v = [0]  # 某株草药的价值
for i in range(M):
    a, b = map(int, input().split())
    t.append(a)
    v.append(b)
dp = [[0]*(T+1) for i in range(M+1)]

for i in range(1, M+1):
    for j in range(1, T+1):
        if t[i] > j:
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i-1][j], dp[i-1][j-t[i]]+v[i])

print(dp[M][T])
  1. 开心的金明-554
# 背包问题
N, m = map(int, input().split()) # 总钱数,物品个数
v = [0] # 价格
p = [0] # 重要度
for i in range(m):
    a, b = map(int, input().split())
    v.append(a)
    p.append(b)
dp = [[0]*(N+1) for _ in range(m+1)]

for i in range(1, m+1):
    for j in range(1, N+1):
        if v[i] > j:
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]]+p[i]*v[i])

print(dp[m][N])
  1. 传球游戏-525
n, m = map(int, input().split()) # n个同学传m次
dp = [[0]*(n+1) for _ in range(m+1)]
# dp[0][1] = 1
dp[1][2] = 1
dp[1][n] = 1

# dp[i][j]: 传了i次后,球在j同学手里有几种可能
for i in range(2, m+1):
    for j in range(1, n+1):
        if j == n:
            dp[i][j] = dp[i-1][j-1] + dp[i-1][1]
        elif j == 1:
            dp[i][j] = dp[i-1][j+1] + dp[i-1][n]

        else:
            dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1]
print(dp[m][1])
  1. 摆花-389
n, m = map(int, input().split()) # n种花m盆
a = list(map(int, input().split()))
assert len(a) == n
dp = [[0]*(m+1) for _ in range(n+1)]

# dp[i][j]: i种j盆时的方案数

# 只有一种花
for i in range(a[0]+1):
    dp[1][i] = 1
# m = 0
for i in range(1, n+1):
    dp[i][0] = 1

for i in range(2, n+1):
    for j in range(1, m+1):
        for k in range(a[i-1]+1):
            if j - k >= 0:
                dp[i][j] = (dp[i][j] + dp[i-1][j-k]) % int(1e6+7)

print(dp[n][m])
  1. 最优包含-239
    和编辑距离有一些像。
S = input()
T = input()
dp = [[int(1e3)]*(len(T)+1) for i in range(len(S)+1)]
# T为空
for i in range(len(S)+1):
    dp[i][0] = 0

for i in range(1, len(S)+1):
    for j in range(1, len(T)+1):
        if S[i-1] == T[j-1]: # 字符串中的第i个字符和第j个字符
            dp[i][j] = dp[i-1][j-1]
        else:
            dp[i][j] = min(dp[i-1][j-1]+1, dp[i-1][j])

print(dp[len(S)][len(T)])

你可能感兴趣的:(蓝桥杯,蓝桥杯,python,动态规划)