AI刷题(七) | 豆包MarsCode AI刷题

52 阅读6分钟

动态规划


小U的最大连续移动次数问题

问题描述

小U决定在一个 m×nm×n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:

  1. 只能上坡或者下坡,不能走到高度相同的点。
  2. 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。
  3. 每个位置只能经过一次,不能重复行走。

任务是帮助小U找到他在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。

例如在以下2x2的地图中:

1 2
4 3

中庸行者可以选择移动顺序 3 -> 4 -> 1 -> 2,最大移动次数为3。


测试样例

样例1:

输入:m = 2, n = 2, a = [[1, 2], [4, 3]]
输出:3

样例2:

输入:m = 3, n = 3, a = [[10, 1, 6], [5, 9, 3], [7, 2, 4]]
输出:8

样例3:

输入:m = 4, n = 4, a = [[8, 3, 2, 1], [4, 7, 6, 5], [12, 11, 10, 9], [16, 15, 14, 13]]
输出:11

解题思路

这是一个图的遍历问题,可以通过深度优先搜索(DFS)来求解,同时结合回溯以保证每个位置只能被访问一次。

为了优化效率,可以引入记忆化搜索(Memoization)记录从某点开始,分别以“上坡”或“下坡”为起点的最长路径长度,避免重复计算。

问题核心:

  • 路径状态的维护:路径的交替性要求我们在每次移动中记录状态(当前是上坡还是下坡)。
  • 避免重复计算:在尝试所有起点时,路径会出现大量重复计算,需要通过记忆化搜索优化。
  • 方向遍历:每个点最多向上下左右四个方向移动。

算法步骤

  1. 数据结构设计
  • 使用二维数组 dp[x][y][state]
    • dp[x][y][1] 表示从位置 (x, y) 出发,当前状态为“上坡”时的最长路径长度。
    • dp[x][y][0] 表示从位置 (x, y) 出发,当前状态为“下坡”时的最长路径长度。
  • 使用方向数组 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] 表示上下左右四个方向。
  1. DFS 定义与递归逻辑
  • 递归结束条件:如果当前点 (x, y) 的某个状态已经计算过(在 dp 中有值),直接返回。
  • 遍历相邻点: - 对每个相邻点 (nx, ny)
    • 检查边界条件(是否在地图范围内);
    • 检查高度条件:
      • 如果当前是“上坡”,则下一点高度必须更高;
      • 如果当前是“下坡”,则下一点高度必须更低。
    • 如果满足条件,则递归计算以 (nx, ny) 为起点的最长路径长度。
  • 回溯与结果更新
    • 每次递归返回后更新当前点的最大路径长度。
    • 将结果存储到 dp[x][y][state] 中,避免重复计算。
  1. 遍历地图所有点
  • 从地图的每个点 (i, j) 开始,分别尝试以“上坡”和“下坡”为起点,计算最长路径长度。
  • 记录所有起点的最大值作为最终结果。

代码

def solution(m: int, n: int, a: list) -> int:
    # 初始化访问标记数组
    visited = [[False] * n for _ in range(m)]
    
    # 定义DFS函数
    def dfs(x, y, is_uphill):
        # 标记当前位置为已访问
        visited[x][y] = True
        # 初始化当前路径的最大移动次数
        max_path_moves = 0
        
        # 遍历四个方向
        for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
            nx, ny = x + dx, y + dy
            if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny]:
                # 判断是否满足交替上坡/下坡的条件
                if is_uphill and a[nx][ny] > a[x][y]:
                    max_path_moves = max(max_path_moves, 1 + dfs(nx, ny, False))
                elif not is_uphill and a[nx][ny] < a[x][y]:
                    max_path_moves = max(max_path_moves, 1 + dfs(nx, ny, True))
        
        # 回溯:标记当前位置为未访问
        visited[x][y] = False
        return max_path_moves
    
    # 初始化最大移动次数
    max_moves = 0
    
    # 从每个位置开始进行DFS
    for i in range(m):
        for j in range(n):
            max_moves = max(max_moves, dfs(i, j, True))
            max_moves = max(max_moves, dfs(i, j, False))
    
    return max_moves

if __name__ == '__main__':
    print(solution(2, 2, [[1, 2], [4, 3]]) == 3)
    print(solution(3, 3, [[10, 1, 6], [5, 9, 3], [7, 2, 4]]) == 8)
    print(solution(4, 4, [[8, 3, 2, 1], [4, 7, 6, 5], [12, 11, 10, 9], [16, 15, 14, 13]]) == 11)

01背包最大价值问题

问题描述

一个旅行者外出旅行时需要将 n 件物品装入背包,背包的总容量为 m。每个物品都有一个重量和一个价值。你需要根据这些物品的重量和价值,决定如何选择物品放入背包,使得在不超过总容量的情况下,背包中物品的总价值最大。

给定两个整数数组 weights 和 values,其中 weights[i] 表示第 i 个物品的重量,values[i] 表示第 i 个物品的价值。你需要输出在满足背包总容量为 m 的情况下,背包中物品的最大总价值。


测试样例

样例1:

输入:n = 3 ,weights = [2, 1, 3] ,values = [4, 2, 3] ,m = 3
输出:6

样例2:

输入:n = 4 ,weights = [1, 2, 3, 2] ,values = [10, 20, 30, 40] ,m = 5
输出:70

样例3:

输入:n = 2 ,weights = [1, 4] ,values = [5, 10] ,m = 4
输出:10

解题思路

这是一个经典的01背包问题,用动态规划解决即可

对于每件物品,有两种选择:

  1. 不放入背包
  2. 放入背包

目标是找到一种选择,使得在总重量不超过 mmm 的情况下,背包中的物品总价值最大

算法步骤

  • 定义状态:
    • dp[j] 表示背包容量为 jjj 时,背包可以达到的最大总价值。
    • 初始化 dp[0] = 0,即背包容量为 0 时,总价值为 0。
  • 状态转移方程:
    • 对于第 i 件物品,其重量为 weights[i],价值为 values[i]
      • 如果不选这件物品:dp[j] = dp[j](状态保持不变)。
      • 如果选这件物品:dp[j] = max(dp[j], dp[j - weights[i]] + values[i]),即比较选与不选的总价值。
    • 从容量 m 倒序更新到 weights[i],避免重复使用同一物品。

代码

``python def solution(n: int, weights: list, values: list, m: int) -> int: dp = [[0] * (m + 1) for _ in range(n + 1)]

for i in range(1, n + 1):
    for j in range(m + 1):
        if weights[i - 1] > j:
            dp[i][j] = dp[i - 1][j]
        else:
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1])

return dp[n][m]

if name == 'main': print(solution(n = 3, weights = [2, 1, 3], values = [4, 2, 3], m = 3) == 6) print(solution(n = 4, weights = [1, 2, 3, 2], values = [10, 20, 30, 40], m = 5) == 70) print(solution(n = 2, weights = [1, 4], values = [5, 10], m = 4) == 10)