https://leetcode-cn.com/problems/max-dot-product-of-two-subsequences/
dfs枚举版本,超时。
参数状态包括 之前的最大和,以及两个位置。
sum是sum+nums1[i]*nums2[j]。转换为动态规划的时候,dp[i][j],是包括两个最后结束位置i,j的值的点乘的。所以答案要不停的记住最大值。
class Solution {
public:
int ans=-0x3f3f3f3f;
int best_sum[505][505];
int tag[505][505];
void dfs(int sum,int pos1,int pos2,vector<int>& nums1, vector<int>& nums2){
if(tag[pos1][pos2]!=0 && best_sum[pos1][pos2]>sum)
return;
tag[pos1][pos2]=1;
best_sum[pos1][pos2]=sum;
if(sum>ans && pos1!=0 && pos2!=0)
ans=sum;
if(pos1>=nums1.size())
return;
if(pos2>=nums2.size())
return;
for(int i=pos1;i<nums1.size();i++){
for(int j=pos2;j<nums2.size();j++){
dfs(sum+nums1[i]*nums2[j],i+1,j+1,nums1,nums2);
}
}
}
int maxDotProduct(vector<int>& nums1, vector<int>& nums2) {
memset(tag,0,sizeof(tag));
dfs(0,0,0,nums1,nums2);
return ans;
}
};
dfs转为动态规划的版本
class Solution {
public:
int dp[505][505];
int maxDotProduct(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size();
int m=nums2.size();
int ans=-0x3f3f3f3f;
int max_val=-0x3f3f3f3f;
int max_dp_arr[m];
memset(max_dp_arr,0,sizeof(max_dp_arr));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int max_dp=0;
if(j-1>=0)
max_dp=max(max_dp,max_dp_arr[j-1]);
int val=nums1[i]*nums2[j];
max_val=max(max_val,val);
dp[i][j]=max_dp+val;
ans=max(ans,dp[i][j]);
}
for(int j=0;j<m;j++){
max_dp_arr[j]=max(max_dp_arr[j],dp[i][j]);
if(j-1>=0)
max_dp_arr[j]=max(max_dp_arr[j],max_dp_arr[j-1]);
}
}
if(max_val<0)
return max_val;
return ans;
}
};
动态规划版本2
dp[i][j]是不一定包括最后结束位置的,代码简介很多。但是思路高呀。
转移的关键地方是,只是一个数组增加一个位置的时候,不考虑增加新的点乘。
class Solution {
public:
int dp[505][505];
int maxDotProduct(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size();
int m=nums2.size();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
dp[i][j]=nums1[i]*nums2[j];
if(i-1>=0)
dp[i][j]=max(dp[i][j],dp[i-1][j]);
if(j-1>=0)
dp[i][j]=max(dp[i][j],dp[i][j-1]);
if(i-1>=0 && j-1>=0){
dp[i][j]=max(dp[i][j],dp[i-1][j-1]);
dp[i][j]=max(dp[i][j],dp[i-1][j-1]+nums1[i]*nums2[j]);
}
}
}
return dp[n-1][m-1];
}
};