取数游戏2
1、原问题:每次能从a的左端或者右端取一个值和取b的最左值相乘后求总和
2、子问题(终态思考): 最小区间取值都与b的最右端相乘后随着len的扩大b值逐渐向左取
3、状态参数:len(从1开始),l,r
4、状态转移方程:
- dp[l][r] = max(dp[l][r] , dp[l][r-1]+a[r]*b[n-len+1]);
- dp[l][r] = max(dp[l][r] , dp[l+1][r]+a[l]*b[n-len+1]);
5、初始化:初始化dp都为0
6、是否优化:否
7、实现方式:逆向思维
8、答案位置:dp[1][n];
9、思考:为何无k值摆动求最大值?
- 因为该题不是无规律的求两块区间的值来比较大小,他是有规律的要么取左值,要么取右值。
- 主要的原题思想是:取了左值或者右值后,区间缩小一位,此时的要求情况是小一位的区间已经有了最优值,但是还没有
- 逆向思维(终态思考):从最小区间(长度为1)开始去乘最右端的B,求值后取最优。然后逐渐扩大len范围,同时B值向左取
```int t,n;
void solve()
{
cin>>n;
vector<vector<int> > dp(1010,vector<int>(1010,0));
vector<int>a(2*n+2);
vector<int>b(2*n+2);
for(int i = 1; i <= n; ++i) cin >> a[i];
for(int i = 1; i <= n; ++i) cin >> b[i];
for(int len = 1; len <= n; ++len)
for(int l = 1; l <= n-len +1; ++l)
{
int r = l + len -1;
dp[l][r] = max(dp[l][r] , dp[l][r-1]+a[r]*b[n-len+1]);
dp[l][r] = max(dp[l][r] , dp[l+1][r]+a[l]*b[n-len+1]);
}
cout<<dp[1][n]<<endl;
}
int main()
{
cin >> t;
while (t--)
{
solve();
}
return 0;
}