Codeforces 987 C Three displays

 AC通道

题目大意:

从一个序列中选出一个符合条件i < j < k && s[i] < s[j] < s[k] 的序列,求c[i] + c[j] + c[k] 的最小值

思路:

dp[i][1]表示以 i 为结尾的一元组的最小值,dp[i][2]表示 i 结尾的二元组的最小值,dp[i][3]表示 i 结尾的三元组的最小值

显而易见

dp[i][1] = c[i];
if(s[i] > s[j]){
    dp[i][3] = min(dp[i][3], dp[j][2] + c[i]);
    dp[i][2] = min(dp[i][2], dp[j][1] + c[i]);
}

dp[i][3]可以有前面的二元组推出来,只需要一个循环遍历 i ,另一个循环遍历 i 前面的 j ,一边判断一边更新即可

#include <bits/stdc++.h>
using namespace std;
const int N = 3010;
typedef long long ll;
int n;
ll s[N], c[N];
ll dp[N][5];
const int inf = 0x3f3f3f3f;
int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++){
		scanf("%lld", &s[i]);
	}
	for (int i = 1; i <= n; i++){
		scanf("%lld", &c[i]);
	}
	/*
		i < j < k 
		s[i] < s[j] < s[k]
		c[i] + c[j] + c[k] 最小 
	*/
//	if(s[i + 1] > s[i])dp[i + 1][3] = min(dp[i][3], dp[i][2] + c[i]);
	memset(dp, 0x3f, sizeof (dp));
	dp[1][1] = c[1];
	for (int i = 2; i <= n; i++){
		dp[i][1] = c[i];
		for (int j = 1; j < i; j++){
			if(s[i] > s[j]){
				dp[i][3] = min(dp[i][3], dp[j][2] + c[i]);
				dp[i][2] = min(dp[i][2], dp[j][1] + c[i]);
			}
		}
	}
	ll res = dp[1][3];
	for (int i = 1; i <= n; i++)res = min(res, dp[i][3]);
	res >= inf ? puts("-1") : printf("%lld\n", res);
	return 0;
}

 

posted @ 2019-09-19 19:14  correct  阅读(103)  评论(0)    收藏  举报