1- # [ 3290. 最高乘法得分] ( https://leetcode.cn/problems/maximum-multiplication-score/description/ )
1+ # 3290. 最高乘法得分
22
3- > ** 日期:** 2024-09-15
4- > ** 所用时间:** 12min
3+ > ** 日期** :2024-09-15
4+ > ** 所用时间** :12min
5+ > ** 知识点** :动态规划、记忆化搜索
56
6- ## 1. 记忆化搜索
7+ ## 1. 题目描述
78
8- 状态表示:$dfs(i, j)$ 表示在区间 $ [ 0, i ] $ 内选择 $j$ 个数
9+ 给定两个整数数组 ` a ` 和 ` b ` ,长度分别为 ` n ` 和 ` m ` (保证 $m \ge n$)。
910
10- 状态计算:对于第$i$个数来说,有两种做法:选和不选
11-
12- 1 . 选第$i$个数,则$dfs(i - 1, j - 1) + a[ i] \times b[ j - 1] $
13- 2 . 不选,则$dfs(i - 1, j)$
14-
15- 最终的状态计算方程如下:
11+ 你需要从 ` b ` 中** 按顺序** 选出恰好 ` n ` 个下标 $j_0 < j_1 < \cdots < j_ {n-1}$,并将 ` a[i] ` 与 ` b[j_i] ` 一一配对。** 乘法得分** 定义为所有配对乘积之和:
1612
1713$$
18- \max(dfs(i - 1, j), dfs(i - 1, j - 1) + a[i] \times b[j - 1])
14+ \sum_{i=0}^{n-1} a[i] \times b[j_i]
1915$$
2016
17+ 求可能得到的** 最高乘法得分** 。
18+
19+ ** 示例 1:**
20+
21+ - ** 输入** :a = [ 2, 1, 3] , b = [ 1, 2, 3, 4]
22+ - ** 输出** :20
23+ - ** 解释** :从 b 中按顺序选 3 个下标与 a 配对,使乘积和最大即可得到 20。
24+
25+ ** 示例 2:**
26+
27+ - ** 输入** :a = [ 1, 2] , b = [ 1, 2, 3]
28+ - ** 输出** :8
29+ - ** 解释** :选 b 的下标 [ 1, 2] ,得分为 1* 2 + 2* 3 = 8。
30+
31+ ** 提示:**
32+
33+ - $1 \le n \le m$
34+ - $1 \le n, m \le 500$
35+ - 数组元素为整数(可能为负,以题目约束为准)。
36+
37+ ## 2 记忆化搜索
38+
39+ 状态:$dfs(i, j)$ 表示在数组 ` a ` 的前 $i+1$ 个元素与数组 ` b ` 的前 $j+1$ 个元素中,已按顺序配对完 $a[ 0..i] $ 与某 $j+1$ 个位置中的 $i+1$ 个来自 ` b ` 的元素时,能得到的最大得分(即从 ` b[0..j] ` 里选恰好 $i+1$ 个做配对)。
40+
41+ - ** 当 $i < 0$** :无元素可配,返回 $0$。
42+ - ** 当 $i = j$** :` a[0..i] ` 与 ` b[0..j] ` 长度均为 $i+1$,必须一一配对,故 $dfs(i, j) = dfs(i-1, j-1) + a[ i] \times b[ j] $。
43+ - ** 当 $i \neq j$** :要么将 $a[ i] $ 与 $b[ j] $ 配对,得 $dfs(i-1, j-1) + a[ i] \times b[ j] $;要么不选 $b[ j] $,得 $dfs(i, j-1)$。取两者最大值。
44+
45+ 复杂度分析:
46+
2147- 时间复杂度:$O(nm)$
2248- 空间复杂度:$O(nm)$
2349
@@ -28,42 +54,24 @@ class Solution:
2854 def maxScore (self , a : List[int ], b : List[int ]) -> int :
2955 @cache
3056 def dfs (i , j ):
31- if j == 0 :
32- return 0
3357 if i < 0 :
34- return - inf
35- return max (dfs(i - 1 , j), dfs(i - 1 , j - 1 ) + a[j - 1 ] * b[i])
36- return dfs(len (b) - 1 , 4 )
58+ return 0
59+ if i == j:
60+ return dfs(i - 1 , j - 1 ) + a[i] * b[j]
61+ return max (dfs(i - 1 , j - 1 ) + a[i] * b[j], dfs(i, j - 1 ))
62+ return dfs(len (a) - 1 , len (b) - 1 )
3763```
3864
39- ## 2. 第二种记忆化搜索的状态定义
40-
41- ### 状态表示
42-
43- $dfs(i, j, k)$ 表示在数组 $a$ 的前 $i$ 个元素和数组 $b$ 的前 $j$ 个元素中选择 $k$ 个数
44-
45- ### 状态计算
46-
47- 对于第 $i$ 个元素和第 $j$ 个元素来说,有两种情况:
65+ ## 3 递推(DP 表)
4866
49- 1 . 如果 $i = j$,则必须同时选择这两个元素,状态转移为 $dfs(i - 1, j - 1, k - 1) + a[ i] \times b[ j] $
50- 2 . 如果 $i \neq j$,则有两种选择:
51- - 不选择数组 $b$ 的第 $j$ 个元素,状态转移为 $dfs(i, j - 1, k)$
52- - 同时选择数组 $a$ 的第 $i$ 个元素和数组 $b$ 的第 $j$ 个元素,状态转移为 $dfs(i - 1, j - 1, k - 1) + a[ i] \times b[ j] $
67+ 将上述记忆化搜索改为递推:$f[ i] [ j ] $ 表示考虑 ` a ` 的前 $i$ 个元素与 ` b ` 的前 $j$ 个元素时能得到的最大得分(即从 ` b[0..j-1] ` 中选恰好 $i$ 个与 ` a[0..i-1] ` 配对的最大和)。
5368
54- ### 边界条件
69+ - 当 $i = j$:必须配对 $a[ i-1] $ 与 $b[ j-1] $,故 $f[ i] [ j ] = f[ i-1] [ j-1 ] + a[ i-1] \times b[ j-1] $。
70+ - 当 $i \neq j$:要么配对 $a[ i-1] $ 与 $b[ j-1] $,得 $f[ i-1] [ j-1 ] + a[ i-1] \times b[ j-1] $;要么不选 $b[ j-1] $,得 $f[ i] [ j-1 ] $。取最大值。
5571
56- - 当 $k = 0$ 时,说明已经选择了 $k$ 个数,返回 0
57- - 当 $i < 0$ 或 $j < 0$ 时,说明数组 $a$ 或 $b$ 已经遍历完了,返回 0
72+ 按 $i$、$j$ 递增递推,答案为 $f[ n] [ m ] $。
5873
59- ### 状态计算方程
60-
61- $$
62- \begin{cases}
63- dfs(i - 1, j - 1, k - 1) + a[i] \times b[j], & \text{if } i = j \\
64- \max(dfs(i, j - 1, k), dfs(i - 1, j - 1, k - 1) + a[i] \times b[j]), & \text{if } i \neq j
65- \end{cases}
66- $$
74+ 复杂度分析:
6775
6876- 时间复杂度:$O(nm)$
6977- 空间复杂度:$O(nm)$
7381``` python
7482class Solution :
7583 def maxScore (self , a : List[int ], b : List[int ]) -> int :
76- @cache
77- def dfs (i , j , k ):
78- if k == 0 or i < 0 or j < 0 :
79- return 0
80- if i == j:
81- return dfs(i - 1 , j - 1 , k - 1 ) + a[i] * b[j]
82- return max (dfs(i, j - 1 , k), dfs(i - 1 , j - 1 , k - 1 ) + a[i] * b[j])
83- return dfs(len (a) - 1 , len (b) - 1 , 4 )
84+ n, m = len (a), len (b)
85+ f = [[0 ] * (m + 1 ) for _ in range (n + 1 )]
86+
87+ for i, x in enumerate (a):
88+ for j, y in enumerate (b):
89+ if i == j:
90+ f[i + 1 ][j + 1 ] = f[i][j] + x * y
91+ else :
92+ f[i + 1 ][j + 1 ] = max (f[i][j] + x * y, f[i + 1 ][j])
93+ return f[n][m]
8494```
0 commit comments