蓝桥·算法赛——第03场

1-双十一的祈祷

2-疯狂的促销

3-被替换的身份证

t = int(input())
p = "3456789XJQKA2MF"
def lar(a):
    return max(p.index(a[0]), p.index(a[1]))

for i in range(t):
    s, j = input().split()
    if s[0] == s[1] or s == "MF" or s == "FM":
    	print("ShallowDream")
    else:
        if j == "MF" or j == "FM":
            print("Joker")
        elif lar(s) >= lar(j):
            print("ShallowDream")
        else:
            print("Joker")

4-迷宫逃脱

方法1:动态规划

from math import gcd # gcd(任何数, 0) = abs(任何数)

N, M, Q = map(int, input().split())
# 任意(i, j)均是从(i - 1, j)和(i, j - 1)转移
a = [[0] * (M + 1) for _ in range(N + 1)]
for i in range(1, N + 1):
    temp = list(map(int, input().split()))
    for j in range(1, M + 1):
        a[i][j] = temp[j - 1]
# dp[i][j][k]走到(i, j)消耗 k 把钥匙的最大值
dp = [[[0] * (Q + 1) for _ in range(M + 1)] for _ in range(N + 1)]
dp[1][1][0] = a[1][1] # 完成初始化 i, j, k 均只与前一个相关
for i in range(1, N + 1): # 针对每一个位置
    for j in range(1, M + 1):
        """ 情况1:从a[i - 1][j]转移 """
        if gcd(a[i][j], a[i - 1][j]) != 1: # 无需钥匙
            for k in range(Q + 1): # 更新每一个维度
                if dp[i - 1][j][k] != 0: # 否则不能从(i - 1,j)转移
                    dp[i][j][k] = dp[i - 1][j][k] + a[i][j]
        else: # 需要钥匙 Q 从 1 开始 dp[i][j][0] = 0
            for k in range(1, Q + 1): # 更新每一个维度
                if dp[i - 1][j][k - 1] != 0:  # 否则不能从(i - 1,j)转移
                    dp[i][j][k] = dp[i - 1][j][k - 1] + a[i][j]
        """ 情况2:从a[i][j - 1]转移 需要与第一种情况做比较"""
        if gcd(a[i][j], a[i][j - 1]) != 1:  # 无需钥匙
            for k in range(Q + 1):  # 更新每一个维度
                if dp[i][j - 1][k] != 0:  # 否则不能从(i,j - 1)转移
                    dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k] + a[i][j])
        else:  # 需要钥匙Q从1开始 dp[i][j][k] = 0
            for k in range(1, Q + 1):  # 更新每一个维度
                if dp[i][j - 1][k - 1] != 0:  # 否则不能从(i,j - 1)转移
                    dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k - 1] + a[i][j])
ans = 0
for i in range(Q + 1): # 寻找到达(N, M)缩小后钥匙不超过 Q 把的最大值
    ans = max(ans, dp[N][M][i])
print(ans if ans != 0 else -1)

方法2:记忆化搜索

import sys
from math import gcd

sys.setrecursionlimit(1000010)
def dfs(i, j, k): # 和动态规划的类似
    if k == -1: # 出口1:保证 dp[i][j][k] 不大于 0 即不可达
        return -sys.maxsize
    if i == N and j == M: # 出口2:达到最低端 类似于初始化dp[1][1][0] = a[1][1]
        return a[N][M]
    if dp[i][j][k] != -sys.maxsize: # 记忆化
        return dp[i][j][k]
    """情况1:往左走(i, j + 1)"""
    if j + 1 <= M: # 没有越界
        if gcd(a[i][j], a[i][j + 1]) == 1: # 需要钥匙
            dp[i][j][k] = max(dp[i][j][k], dfs(i, j + 1, k - 1) + a[i][j])
        else: # 不要钥匙
            dp[i][j][k] = max(dp[i][j][k], dfs(i, j + 1, k) + a[i][j])
    """情况2:往下走(i + 1, j)"""
    if i + 1 <= N:
        if gcd(a[i][j], a[i + 1][j]) == 1: # 需要钥匙
            dp[i][j][k] = max(dp[i][j][k], dfs(i + 1, j, k-1) + a[i][j])
        else: # 不要钥匙
            dp[i][j][k] = max(dp[i][j][k], dfs(i + 1, j, k) + a[i][j])
    return dp[i][j][k]

"""读入数据"""
N, M, Q = map(int, input().split())
a = [[0] * (M + 1) for _ in range(N + 1)]
for i in range(1, N + 1):
    temp = list(map(int, input().split()))
    for j in range(1, M + 1):
        a[i][j] = temp[j - 1]
# 初始化为 -inf 表示不可到达
dp = [[[-sys.maxsize] * (Q + 1) for _ in range(M + 1)] for _ in range(N + 1)]
ans = dfs(1, 1, Q)
print(ans if ans > 0 else -1)

5-深秋的苹果

def check(arr, Sum, length, count, num):
    ind = 1; val = 0; cnt = 1
    for i in range(1, length + 1):
        val += arr[i] * (Sum[i - 1] - Sum[ind - 1])
        if val >= num: # 重新开始一段
            val = 0; ind = i; cnt += 1
    return cnt <= count # 在 num 的条件下 所得段数小于等于要求 说明 num 小或等于

N, M = map(int, input().split())
lst = [0] + list(map(int, input().split()))
S = [0] * (N + 1) # 前缀和
for i in range(1, N + 1):
    S[i] = S[i - 1] + lst[i]
left = 0; right = 2 * 10 ** 18
while left <= right:
    mid = (left + right) >> 1
    if(check(lst, S, N, M, mid)): # mid小或等于
        right = mid - 1
    else:
        left = mid + 1
print(right)

6-鲜花之海

def calc(N, K):  # 计算下三角形 K 所在横纵坐标
    left = 1; right = N
    while left <= right:
        mid = (left + right) >> 1
        if mid * (mid + 1) >= 2 * K:
            right = mid - 1
        else:
            left = mid + 1
    K -= right * (right + 1) // 2
    return K, left - K + 1

for _ in range(int(input())):
    N, K = map(int, input().split())
    if 2 * K <= N * (N + 1): # 当前数字在三角形下面
        x, y = calc(N, K)
    else: # 当前数字在三角形上方
        K = N * N - K + 1
        x, y = calc(N, K)
        x = N - x + 1; y = N - y + 1
    print(x, y)

7-斐波拉契跳跃

8-星石传送阵

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

胆怯与勇敢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值