不知道为什么标题连小白都不能起
题目描述
输入描述
输出描述
输入样例1
3
1 1 1
输出样例1
6
样例1说明
输入样例2
3
1 2 3
输出样例2
14
样例2说明
区间 dp 的板子题,对于环形问题,首先开两倍长度断环成链,使环形问题变为直线问题。本题中,虽然可以自由选择向左或向右进行移动,但由于需要选择尚未被跳过的位置的限制,因此仅需要考虑对于某个点,上一步是从左边来还是右边来,同时注意每一步权值 i 的存在。
本题以四个点举例,可以发现断环成链后,以 2 出发并从两个方向走完所有点的方案分别为从 2 到 5 和从 6 到 3。为了简化,本题以状态 f [ l ][ r ] 表示在不考虑方向情况下的端点,即该状态即可表示从 l 走到 r,也可表示从 r 走到 l,保证 l ≤ r。可以发现在该样例中,以 2 为起点但往不同方向行走是由两种状态表示的,而与其中 f [ 2 ][ 5 ] 共享一种状态的是 1 - 4 - 3 - 2 ,即对调起点和终点。
因此对于每一种状态,仅需要比较该状态是由左向右还是由右向左的收益更大,更大的即为以该状态的两个维度为起点和终点时区间内的最大值。
状态转移方程:
f [ l ] [ r ] = m a x ( f [ l ] [ r − 1 ] + l e n ∗ a [ r ] , f [ l + 1 ] [ r ] + l e n ∗ a [ l ] ) ; f[l][r] = max(f[l][r - 1] + len * a[r], f[l + 1][r] + len * a[l]); f[l][r]=max(f[l][r−1]+len∗a[r],f[l+1][r]+len∗a[l]);
其中,l、r 为某一区间的左右端点,并分为从 l 由左向右跳到 r 点和从 r 从右向左跳到 l 点两种情况进行讨论,并加上对应步数的贡献,其中 len 标记的为步数。
参考代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[4005][4005]={
0};
ll a[4005];
int main(){
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
f[i][i] = f[i + n][i + n] = a[i + n] = a[i];
}
ll res = 0;
for (int len = 2; len <= n; ++len) {
for (int l = 1; l + len - 1 <= n + n; ++l) {
int r = l + len - 1;
f[l][r] = max(f[l][r - 1] + len * a[r], f[l + 1][r] + len * a[l]);
res = max(res, f[l][r]);
}
}
cout << res;
return 0;
}