Codeforces 987 C Three displays
题目大意:
从一个序列中选出一个符合条件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;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12862032.html

浙公网安备 33010602011771号