C. Three displays codeforces (dp)

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/PinappleMi/article/details/80531860