题意: 给你一组序列,让你从中挑选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);
}