融合目标计算问题 | 豆包MarsCode AI刷题

69 阅读6分钟

问题简化

给定一个包含 n (1 ≤ n ≤ 20) 个目标指标的数组,每个目标指标有两个可能的值,计算所有可能的选择组合,使得它们的乘积落在一个指定的区间 [L, R] 内,即最终的融合结果。最后,输出一个整数,表示有多少种选择组合的乘积在区间 [L, R] 内。

关键点:

  1. 选择组合:每个目标有两个选择,形成 2^n 种组合。
  2. 乘积计算:对每个组合,计算它们的乘积。
  3. 区间判断:判断每个组合的乘积是否落在区间 [L, R] 内。
  4. 结果输出:输出满足条件的组合数量

解题思路

核心:通过暴力枚举所有可能的选择组合来计算最终融合结果,并判断该结果是否落在给定的区间 [L, R] 内。

  1. 位运算表示选择组合
  • 每个目标有两种选择,我们可以使用二进制位来表示每个目标的选择。假设有 n 个目标,每个目标可以选择第一个或第二个变换值,总共有 2^n 种可能的选择组合。
  • 每个二进制数的每一位表示选择某个目标的变换方式。例如,若 n = 2,则可能的选择组合如下:
    • 00 表示都选择第一个变换值
    • 01 表示第一个目标选择第一个变换值,第二个目标选择第二个变换值
    • 10 表示第一个目标选择第二个变换值,第二个目标选择第一个变换值
    • 11 表示都选择第二个变换值
  1. 计算融合结果
  • 对于每个选择组合,通过位运算来决定每个目标使用哪个变换值。如果当前目标选择的是第一个变换值,则乘上 f[i][0],否则乘上 f[i][1]
  1. 判断是否在区间内
  • 对每个融合结果,检查它是否落在给定的区间 [L, R] 内,如果是,累加有效的组合数量。

代码实现

以下是使用python的具体实现及其代码解析

def solution(n: int, f: list[list[int]], L: int, R: int) -> int:
    count = 0
  • n: 目标数的数量
  • f: 是一个二维列表,表示每个目标的两个变换值。f[i][0] 表示第 i 个目标的第一个变换值,f[i][1] 表示第二个变换值。
  • L: 区间的下限,目标融合结果必须大于或等于 L
  • R: 区间的上限,目标融合结果必须小于或等于 R
  • count: 用来计数满足条件的选择组合的数量,初始化为 0。
    for mask in range(1 << n):
        product = 1
  • for mask in range(1 << n): 这一行是枚举所有可能的选择组合。1 << n 相当于 2^n,表示 n 个目标的所有组合数。
    • mask 是一个整数,从 0 到 2^n - 1,它的二进制表示可以用来表示每个目标的选择情况。例如,n = 3 时,mask 会从 000(表示每个目标选择第一个变换值)到 111(表示每个目标选择第二个变换值)。
  • product = 1: 每次遍历一个新的组合时,初始化 product 为 1,表示当前选择组合的融合结果。通过后续的计算不断更新 product
        for i in range(n):
            if mask & (1 << i):
                product *= f[i][1]
            else:
                product *= f[i][0]
  • for i in range(n): 遍历所有目标(每个目标对应一个变换值)。对于每个目标,基于当前的 mask 决定选择哪个变换值。
  • if mask & (1 << i): 这行代码用来检查 mask 的第 i 位。如果该位为 1,则表示选择第 i 个目标的第二个变换值(即 f[i][1])。否则,选择第一个变换值(即 f[i][0])。
    • 1 << i 是将数字 1 左移 i 位,产生一个只在第 i 位为 1 ,其余位为 0 的数字。
    • mask & (1 << i) 通过与运算判断 mask 的第 i 位是否为 1。如果是 1,表示选择第二个变换值;如果是 0,则选择第一个变换值。
  • 根据判断结果,product 会乘上对应的变换值(f[i][0] 或 f[i][1]),最终得到该选择组合下的融合结果。
        if L <= product <= R:
            count += 1
  • 判断当前的 product 是否在区间 [L, R] 内。如果满足条件,则将 count 加 1,当前的选择组合是有效的。
    return count
  • 返回 count,即满足条件的选择组合的数量。

主程序部分:

if __name__ == "__main__":
    # Add your test cases here
    print(solution(2, [[1, 2], [3, 4]], 1, 6) == 3)

总结

初看题目时,可能会觉得这道题比较复杂,但实际上,它只是一个典型的组合枚举问题。我们通过位运算枚举所有可能的选择组合,计算每个组合的乘积,并判断该乘积是否在给定的区间 [L, R] 内。最终返回满足条件的有效组合数。完成这道题,我们需要掌握如何使用位运算来表示选择状态,如何处理多个目标的变换值,并有效地计算这些组合的结果。

位运算是一种非常高效的方式来表示多个选择或状态。在这道题中,mask 变量用来表示 n 个目标的每个选择。通过二进制位的不同组合,就能够轻松列举出所有可能的选择,我们只需要一次循环遍历 02^n - 1 的所有 mask,就能包含所有情况。相较于直接用数组或其他结构存储选择,位运算减少了空间和时间的复杂度。同时,在处理多重选择、组合优化等问题时,位运算是一个非常有用的工具。它帮助我们将问题空间压缩并有效地进行遍历,而不会让问题变得过于复杂。

不过,直接枚举也存在一些局限性。例如,这道题的时间复杂度是 O(2^n * n),其中 2^n 是组合数的数量,n 是每个组合中需要计算的乘积项数。这样看来,这个值就有点点大了。所幸,这道题的问题规模不大,n的取值范围为1 ≤ n ≤ 20,这个解法在这种情况下是可以接受的。但是,如果 n 很大,就可能需要考虑优化方案了,比如动态规划等,但对于一般问题而言,直接枚举所有组合已经足够。