题目描述
给定两个长度为n的整数列A和B,每次你可以从A数列的左端或右端取走一个数。假设第i次取走的数为ax,则第i次取走的数的价值vi=bi⋅ax,现在希望你求出∑vi的最大值。
输入描述:
第一行一个数T,表示有T组数据。
对于每组数据,第一行一个整数n,
接下来两行分别给出A数列与B数列。
输出描述:
每一组数据输出一行,最大的∑vi。
题解
这道题还是很好想的,我们每次做的决策就是是选最左端的还是选择最右端的。我们可以设置dp[i][j]表示剩下的区间是从i到j的,也就是我们选了1~i-1和j+1到n。那么很明显,dp[i][j]=max(dp[i-1][j]+a[i]b[k],dp[i][j+1]+a[j]b[k])。在枚举的时候我们可以直接枚举前面选几个来算出后面的位置。
代码
#include<bits/stdc++.h> using namespace std; int a[1050],b[1050]; long long dp[1050][1050]; int main(){ int T; cin>>T; while(T--){ int n; cin>>n; for(int i=1;i<=n;++i)cin>>a[i]; for(int i=1;i<=n;++i)cin>>b[i]; long long ans=0; for(int i=1;i<=n;++i){ for(int j=0;j<=i;++j){ if(!j)dp[j][n-i+j+1]=dp[j][n-i+j+2]+a[n-i+j+1]*b[i]; else if(i==j)dp[j][n-i+j+1]=dp[j-1][n-i+j+1]+a[j]*b[i]; else dp[j][n-i+j+1]=max(dp[j][n-i+j+2]+a[n-i+j+1]*b[i],dp[j-1][n-i+j+1]+a[j]*b[i]); ans=max(ans,dp[j][n-i+j+1]); //cout<<j<<" "<<n-i+j+1<<" "<<dp[j][n-i+j+1]<<endl; } } cout<<ans<<endl; } }