atcoder 163

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章