E
https://atcoder.jp/contests/abc163/tasks/abc163_e
这道题动态规划有点难
i=1,最大的数可以移动到最左边或者最右边。此时剩余的范围分别变为1:5或者2:6
i=2,倒数第二大的数可以移动到边界的最左边或者边界的最右边。由于现在已经移动了2个数组。所以总的范围减少2。
即现在可以枚举的范围是:1:4,2:4,3:6。1:4可以由1:5中数字移动到最右边或者2:4中数字移动到最左边获得。
......
一直到i=5,此时只剩下一个位置。跳出循环,将最后一个数字移动到这个位置。为什么不在循环里面判断呢?
如果继续在循环里面判断,会出现:此时应该是只剩下一个位置,但根据下面的结果,如出现i=3,j=2。此时会尝试把最后一个数字移动到3或2,即f[3][2]=f[3][3]+最后一个数字移动到3的消耗 or f[3][2]=f[2][3]+最后一个数字移动到2的消耗。但是其实最后一个数字不能移动到2(最后一个剩余的位置是3)。
i = 6: 1 0 2 1 3 2 4 3 5 4 6 5 7 6
dfs
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<stack>
#include<sstream>
//#include <Eigen/Dense>
//#include <Eigen/Geometry>
//using namespace Eigen;
using namespace std;
const int maxn = 2005;
int a[maxn];
int p[maxn];
long long dp[maxn][maxn];
int n;
long long dfs(int start,int end,int cur)
{
if (start > end || end < start)
return 0;
if (dp[start][end] != 0)
return dp[start][end];
long long cost1 = 1LL*a[p[cur]] * abs(p[cur] - start) + dfs(start + 1, end, cur + 1);
long long cost2 = 1LL*a[p[cur]] * abs(p[cur] - end) + dfs(start, end - 1, cur + 1);
dp[start][end] = max(cost1, cost2);
return dp[start][end];
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
p[i] = i;
sort(p, p + n, [&](int i, int j) {return a[i] > a[j]; });
cout << dfs(0, n - 1, 0) << endl;
return 0;
}
动态规划
#include<iostream>
#include<algorithm>
using namespace std;
int n;
const int maxn = 2001;
long long a[maxn], p[maxn];
long long dp[maxn][maxn];
int cmp(int i, int j)
{
return a[i] > a[j];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
p[i] = i;
}
sort(p + 1, p + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= i; j++)
{
int l = j + 1;
int r = n - i + j;
if (l - 1 >= 1)
dp[l][r] = max(dp[l][r], dp[l - 1][r] + abs(a[p[i]] * (p[i] - l + 1)));
if (r + 1 <= n)
dp[l][r] = max(dp[l][r], dp[l][r + 1] + abs(a[p[i]] * (p[i] - r - 1)));
//printf("%d %d ", l, r);
}
//printf("\n");
}
long long ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, dp[i][i] + abs(a[p[n]] * (p[n] - i)));
printf("%lld\n", ans);
return 0;
}