力扣3290.最高乘法得分
力扣3290.最高乘法得分
递归 + 记忆化搜索
-
对于b数组,从右往左考虑取不取,如果取则问题变成b[0] ~ b[i-1]间找j - 1个数
- 如果不取,则问题变成b[0] ~ b[i]间找j个数
- 即dfs(i,j) = max(dfs(i-1,j) , dfs(i-1,j-1) + a[j] * b[i])
-
边界:dfs(i,-1) = 0,dfs(-1,j>=0) = -INF
-
终点:dfs(n-1,3);
-
同时引入记忆化搜索,因为只要参数一致,每次的结果都一样,所以遍历过的就不用再遍历
- 初始化成INF即可
-
class Solution { public: long long maxScore(vector<int>& a, vector<int>& b) { int n = b.size(); //用vector<long long>也可以 //需要一个一个填充 vector<array<long long,4>> memo(n); for(auto &row : memo) ranges::fill(row,LLONG_MIN); auto dfs = [&](auto &&dfs,int i,int j) -> long long { //j == -1 if(j < 0) return 0; if(i < 0) //非法 return LLONG_MIN / 2; //引用取出memo[i][j],如果没更新过,就求res的同时更新 auto &res = memo[i][j]; if(res == LLONG_MIN) res = max(dfs(dfs,i-1,j) , dfs(dfs,i-1,j-1) + (long long)a[j] * b[i]); return res; }; return dfs(dfs,n-1,3); } };
1:1递推
-
f[i+1][j+1] 的定义和dfs(i,j)的定义一样
- 将dfs(-1,j>=0) = -INF也翻译,为f[0][j] = -INF;
-
class Solution { public: long long maxScore(vector<int>& a, vector<int>& b) { int n = b.size(); vector<array<long long,5>> f(n+1); //初始化 for(int j=1;j<5;j++) f[0][j] = LLONG_MIN / 2; for(int i = 0;i<n;i++) for(int j=0;j<4;j++) f[i+1][j+1] = max(f[i][j+1],f[i][j] + (long long)a[j] * b[i]); return f[n][4]; } };