atcoder 163

E

https://atcoder.jp/contests/abc163/tasks/abc163_e 

这道题动态规划有点难

atcoder 163_第1张图片

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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include 
//#include 
//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
#include
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;
}

 

你可能感兴趣的:(Atcoder,动态规划,DFS)