题目链接:C. Three displays
题意:给出一个n,接下来两行 每行n个数字,在第二行中找出三个数,下标i j k满足i
思路:
看到这个题,第一感觉就是dp
1.找长度为3的递增序列,那么可以分解成两个子问题i< j j< k
2.dp[2] [i] 表示第i个位置 时候所找到的一组i j满足对应的和最小
状态转移方程:dp[2][i]=min{dp[2][i],dp[1][j]+dp[1][i]};
3.dp[3][i]表示在2的基础上dp ,前i位组成三个数字,对应的最小和
状态转移方程:dp[3][i]=min{dp[3][i],dp[2][j]+dp[1][j]};
dp[1][j]是题目给的的s[j]
第二个方法(朋友提供):
可以遍历整个数组对每个数字进行计算,以当前位为中间,向左找一个最小的数,向右找一个最小的数,组成i j k ,遍历一遍 最小的值就是答案了
代码:
#include<iostream>
#include<algorithm>
using namespace std;
const long long INF=1e10;
long long dp[4][3005],s[30005];
int main()
{
int n,i,j;
cin>>n;
for(i=1;i<=n;++i)
cin>>s[i];
for(i=1;i<=n;++i)
cin>>dp[1][i];
for(i=2;i<=n;++i)
{
dp[2][i]=INF;
for(j=1;j<i;++j)
{
if(s[i]>s[j])
{
dp[2][i]=min(dp[2][i],dp[1][i]+dp[1][j]);
}
}
}
long long ans=INF;
for(i=3;i<=n;++i)
{
dp[3][i]=INF;
for(j=2;j<i;++j)
{
if(s[i]>s[j])
{
dp[3][i]=min(dp[3][i],dp[2][j]+dp[1][i]);
}
}
if(ans>dp[3][i])ans=dp[3][i];
}
if(ans>=INF)cout<<-1;
else cout<<ans;
return 0;
}