CF 987C Three displays(dp)

题意: 给你一组序列,让你从中挑选3个数,他们满足 i < j < k && a[i] < a[j] < a[k],让你找到 a[i] + a[j] + a[k] 的最小值。

思路:其实就是单调递增子序列之后又加了一维表示我现在选择了几个值,那么dp[i][j] 就表示我现在在第i个值选了j个值的时候的最小值,那么dp[i][j] = min (dp[i][j] , dp[k][j-1] + a[i]) 其中 a[i] < a[k]  ,表示的是我在第i个数的时候,选了j本书他是从某个小于i的值(k) 和j-1 本书的时候转移过来的。

上代码:

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 3e3+5;
int a[maxn],b[maxn];
long long dp[maxn][10]; // dp[i][j]表示的是你现在再第i个之后你挑了第j个的时候的最小 值 
//dp[i][j] = dp[k][j-1] + a[j]; 
int main()
{
	int n;
	scanf("%d",&n);
	for(int i = 0 ; i < n ; i++) scanf("%d",&a[i]);
	for(int i = 0 ; i < n ; i++) scanf("%d",&b[i]);
	memset(dp,inf,sizeof(dp));
	for(int i = 0 ; i < n ; i++) dp[i][0] = b[i]; // 初始话一下, 那么第i个数选0本书的时候的最小值为b[i]  0表示的是我已经选了一本书了 
	for(int k = 0 ; k < 3; k ++)
	{
		for(int i = 1 ; i < n ; i++)
		{
			for(int j = 0 ; j < i ; j++)
			{
				if(a[i] > a[j])
				{
					dp[i][k] = min(dp[j][k-1]+b[i],dp[i][k]);
				}
			}
		}
	}
	long long ans = LLONG_MAX;
	for(int i = 0 ; i < n ; i++)
	{
		ans = min(ans,dp[i][2]);
	}
	if(ans > 3e8) ans = -1;
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/wjmwsgj/article/details/80530528