pat顶级1017 The Best Peak Shape (35 point(s))

欢迎访问我的pat顶级题解目录哦 https://blog.csdn.net/richenyunqi/article/details/86751676

题目描述

pat顶级1017 The Best Peak Shape (35 point(s))题目描述

算法设计

这是一道考察最长上升子序列问题(LIS) 的题目。定义数组A[n+1]存储整个序列;定义数组dpLeft[n+1],其中dpLeft[i]表示序列A[1]~A[i]中以A[i]结尾的不包含A[i]的最长上升子序列的长度;定义数组dpRight[n+1],其中dpRight[i]表示序列A[n]~A[i]中以A[i]结尾的不包含A[i]的最长上升子序列的长度。
那么对于A[i],存在以A[i]为中心的peak shape的条件为dpleft[i]>0&&dpRight[i]>0,整个peak shape的长度为dpleft[ans]+dpRight[ans]+1
关于dpLeftdpRight的求解大致相同,以dpLeft为例,其状态转移方程为 d p L e f t [ i ] = m a x { d p L e f t [ i ] , d p L e f t [ j ] + 1 ∣ j &lt; i , A [ j ] &lt; A [ i ] } dpLeft[i]=max\{dpLeft[i],dpLeft[j]+1|j&lt;i,A[j]&lt;A[i]\} dpLeft[i]=max{dpLeft[i],dpLeft[j]+1j<i,A[j]<A[i]}
具体实现可见代码。

C++代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,ans=0;//ans存储最终结果peak number的下标
    scanf("%d",&n);
    int A[n+1],dpleft[n+1]={0},dpRight[n+1]={0};//将dpleft、dpRight均初始化为0
    for(int i=1;i<=n;++i)
        scanf("%d",&A[i]);
    for(int i=1;i<=n;++i)//求解dpLeft
        for(int j=1;j<i;++j)
            if(A[i]>A[j])
                dpleft[i]=max(dpleft[i],dpleft[j]+1);
    for(int i=n;i>=1;--i)//求解dpRight
        for(int j=n;j>i;--j)
            if(A[i]>A[j])
                dpRight[i]=max(dpRight[i],dpRight[j]+1);
    for(int i=1;i<=n;++i)//求解ans
        if(dpleft[i]>0&&dpRight[i]>0&&(dpleft[i]+dpRight[i]>dpleft[ans]+dpRight[ans]||
           (dpleft[i]+dpRight[i]==dpleft[ans]+dpRight[ans]
            &&abs(dpleft[i]-dpRight[i])<abs(dpleft[ans]-dpRight[ans]))))
            ans=i;
    if(ans==0)
        puts("No peak shape");
    else
        printf("%d %d %d",dpleft[ans]+dpRight[ans]+1,ans,A[ans]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值