题目大意:给出两个长度为n的数组,你可以反转一次其任意子数组,也可以不反转,求对应位置的数的乘积之和
即求
∑
1
n
a
[
i
]
∗
b
[
i
]
{\textstyle \sum_{1}^{n}} a[i]*b[i]
∑1na[i]∗b[i]
解法:我们可以先算出其不反转的乘积之和再加上反转任意子区间反转与不反转的乘积之和的差值的最大值就是最终答案了。
求任意反转任意子区间反转与不反转的乘积之和的差值的最大值就需要用到区间DP
AC代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5004;
ll a[maxn],b[maxn];
ll dp[maxn][maxn];//手机双击代码可以全屏看哦
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
}
ll sum=0;
for(int i=1;i<=n;++i){
scanf("%lld",&b[i]);
sum+=a[i]*b[i];
}
ll maxp=0;
for(int l=n;l>=1;--l){//这里从n到1的原因是因为状态转移是从dp[l+1][r-1]到dp[l][r]的,所以需要从n到1
for(int r=l+1;r<=n;++r){
dp[l][r]=dp[l+1][r-1]-a[l]*b[l]-a[r]*b[r]+a[l]*b[r]+a[r]*b[l];
//反转两头,计算差值
maxp=max(maxp,dp[l][r]);//取最大值
}
}
printf("%lld",maxp+sum);
return 0;
}