简单题32 二分数字组合 简单dp | 豆包MarsCode AI刷题

73 阅读2分钟

问题描述

小F面临一个有趣的挑战:给定一个数组,她需要将数组中的数字分为两组。分组的目标是使得一组数字的和的个位数等于给定的 A,另一组数字的和的个位数等于给定的 B。除此之外,还有一种特殊情况允许其中一组为空,但剩余数字和的个位数必须等于 A 或 B。小F需要计算所有可能的划分方式。

例如,对于数组 [1, 1, 1] 和目标 A = 1,B = 2,可行的划分包括三种:每个 1 单独作为一组,其余两个 1 形成另一组。如果 A = 3,B = 5,当所有数字加和的个位数为 3 或 5 时,可以有一组为非空,另一组为空。


测试样例

样例1:

输入:n = 3,A = 1,B = 2,array_a = [1, 1, 1]
输出:3

样例2:

输入:n = 3,A = 3,B = 5,array_a = [1, 1, 1]
输出:1

样例3:

输入:n = 2,A = 1,B = 1,array_a = [1, 1]
输出:2

样例4:

输入:n = 5,A = 3,B = 7,array_a = [2, 3, 5, 7, 9]
输出:0

解题思路

先总体求和判断是哪种情况,然后套用0-1背包模板代码

0-1背包

0-1背包问题是一个经典的动态规划问题,它描述了这样一个场景:给定一组物品,每个物品都有一个重量和一个价值,确定在不超过背包容量限制的情况下,所装物品的最大价值。

问题定义

  • 物品:有 nn 个物品,每个物品 ii 有一个重量 wiw_i 和一个价值 viv_i
  • 背包容量:背包可以承载的最大重量为 WW
  • 目标:选择一些物品装入背包,使得背包中物品的总价值最大,同时不超过背包的容量限制。

动态规划解法

  1. 定义状态:设 dp[i][j]dp[i][j] 表示考虑前 ii 个物品,背包容量为 jj 时的最大价值。

  2. 状态转移方程

    • 如果不取第 ii 个物品,则 dp[i][j]=dp[i1][j]dp[i][j]=dp[i−1][j]

    • 如果取第 ii 个物品(前提是 jwij≥w_i),则 dp[i][j]=dp[i1][jwi]+vidp[i][j]=dp[i−1][j−w_i]+v_i

    • 综合两种情况,状态转移方程为:

      dp[i][j]=max(dp[i1][j],dp[i1][jwi]+vi)dp[i][j]=max⁡(dp[i−1][j],dp[i−1][j−w_i]+v_i)

  3. 初始化dp[0][j]=0dp[0][j]=0 对所有 jj,因为没有物品时价值为00

  4. 计算顺序:按照 ii 从 11 到 nnjj 从 00 到 WW 的顺序填充 dpdp 表。

0-1背包模板

def knapsack(W, w, v):
    n = len(w)
    dp = [[0 for _ in range(W+1)] for _ in range(n+1)]
    
    for i in range(1, n+1):
        for j in range(W+1):
            if j < w[i-1]:
                dp[i][j] = dp[i-1][j]
            else:
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1])
    
    return dp[n][W]

# 示例
W = 50  # 背包容量
w = [10, 20, 30]  # 物品重量
v = [60, 100, 120]  # 物品价值
print(knapsack(W, w, v))  # 输出最大价值

解题代码

def solution(n, A, B, array_a):
    array_sum = 0
    res = 0
    for i in range(n):
        array_a[i] = array_a[i] % 10
        array_sum += array_a[i]
    if array_sum % 10 == A or array_sum % 10 == B:
        res += 1
    if array_sum % 10 != (A + B) % 10:
        return res
    array_a.sort()
    array_a.reverse()
    dp = [0] * (10 * n + 1)
    dp[0] = 1
    for i in range(n):
        for j in range(10 * n, 0, -1):
            if j >= array_a[i]:
                dp[j] += dp[j - array_a[i]]
    for i in range(A, 10 * n + 1, 10):
        res += dp[i]
    return res