26 · 内积
给定长度为NNN的AAA数组,长度为KKK的BBB数组
你可以从AAA数组里取KKK个数
规则如下:
每个AiA_iAi只能被取出一次
i==1ori==Ni==1 \quad or \quad i==Ni==1ori==N 可以直接取出AiA_i\quadAi
2≤i≤N−12 \leq i \leq N-1\quad2≤i≤N−1 若Ai−1A_{i-1}Ai−1 或者 Ai+1A_{i+1}Ai+1 已经取出,则可以取出AiA_iAi
要取出正好KKK个数
即每次可以从AAA数组的最左边或者最右边取走一个数,取走的数从数组中移除
将取出的AiA_iAi按取出的顺序 组成CCC数组
求BBB与CCC的内积最大值
BBB与CCC内积为∑i=0K−1Bi×Ci\sum_{i=0}^{K-1}B_i \times C_i∑i=0K−1Bi×Ci
解释1:
AAA= [1,4,3,2,5]
BBB=[1,2,3,4]
KKK=4
取出A0A_0A0 ,CCC=[1]
取出A4A_4A4 CCC=[1,5]
取出A1A_1A1 CCC=[1,5,4]
取出A2A_2A2 CCC=[1,5,4,3]
BBB·CCC=1*1+2*5+3*4+4*3=35
这只是CCC的一种可行方案,可能不是最优方案
解释2
AAA=[1,2,3,4]
不能直接取出A1A_1A1 因为A0A_0A0和A2A_2A2都没有取出
1≤K≤N≤20001 \leq K \leq N \leq 20001≤K≤N≤2000
1≤Ai,Bi≤1000001 \leq A_i,B_i \leq 1000001≤Ai,Bi≤100000
样例
[2,3,5,1]
[2,1]
取出A0,A1A_0,A_1A0,A1
long long getMaxInnerProduct(vector<int> &A, vector<int> &B)
{
int sizeA = A.size();
int sizeB = B.size();
int64_t max = -1;
vector<int64_t> preLeftVec(sizeA, 0);
vector<int64_t > preRightVec(sizeA, 0);
vector<int64_t > curLeftVec(sizeA, 0);
vector<int64_t > curRightVec(sizeA, 0);
vector<int64_t > emptyVec(sizeA, 0);
for (int i = 0; i < sizeB; i++)
{
//列从左边到右边
for (int j = 0; j <= i; j++)
{
if (0 == j && 0 == i) //第一列
{
curLeftVec[j] = (int64_t)B[i] * (int64_t)A[j];
}
else
{
int64_t right = (sizeA-1) - (i - j -1) ;
int64_t max = -1;
int64_t leftMax = -1;
int64_t rightMax = -1;
if (j - 1 >= 0)
{
leftMax = preLeftVec[j - 1];
}
if (right < sizeA)
{
rightMax = preRightVec[right];
}
max = leftMax > rightMax ? leftMax : rightMax;
curLeftVec[j] = (int64_t)B[i] * (int64_t)A[j] + max;
}
if (curLeftVec[j] > max)
{
max = curLeftVec[j];
}
}
//列从右边到左边
for (int j = sizeA - 1; j >= sizeA - 1 - i; j--)
{
if (sizeA - 1 == j && 0 == i)
{
curRightVec[j] = (int64_t)B[i] * (int64_t)A[j];
}
else
{
int64_t left = i -1 - ((sizeA - 1) - j);
int64_t max = -1;
int64_t leftMax = -1;
int64_t rightMax = -1;
if (left >=0 )
{
leftMax = preLeftVec[left];
}
if (j + 1 < sizeA)
{
rightMax = preRightVec[j + 1];
}
max = leftMax > rightMax ? leftMax : rightMax;
curRightVec[j] = (int64_t)B[i] * (int64_t)A[j] + max;
}
if (curRightVec[j] > max)
{
max = curRightVec[j];
}
}
preLeftVec = curLeftVec;
preRightVec = curRightVec;
curLeftVec = emptyVec;
curRightVec = emptyVec;
}
return max;
}