2023蓝桥杯B组省赛 接龙序列

在这里插入图片描述

 大致思路:应该属于线性DP,子序列问题,通常是去找最xx的一个最值序列(通常是最长)。

序列分为连续或者不连续,连续的有 求连续区间最大和等等,本题为不连续

通常将状态定义为dp[i]以arr[i]结尾的最长子序列这样通常是搭建子问题与原问题的桥梁

本题求去最少多少数能成为接龙序列,其实就是求最长接龙子序列

状态转移方程为

从1-i (k为迭代变量)如果能拼接上 dp[j]=max{dp[j],dp[k] + 1 };

最后得dp[n];

初始化的dp[]={1}

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>
  
using namespace std;
int l[100010],r[100010],dp[100010];
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;++i)
    {
        string s;
        cin>>s;
        l[i]=s[0]-'0',r[i]=s[s.size()-1]-'0';
    }
     
    int res=0;
    for(int i=0;i<n;++i)
    {
        dp[i]=1;
        for(int j=0;j<i;++j)
        {
            if(l[i]==r[j])
            dp[i]=max(dp[i],dp[j]+1);
            res=max(res,dp[i]);
        }
    }
    cout<<n-res<<endl;
     
     
    return 0;
}

这种复杂度是O(n^2)

当然还有另一种办法:由于接龙数列种类比较少并且由于接龙数列的特殊性

对于第i个值来说不可以不找i之前的可以直接与他匹配的因为只有一个并且总共只有10种类型(用G[N]里面存的是以i为结尾的最大值)因此可以直接通过索引去找,优化时间。

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>
 
using namespace std;
 int g[10];//可以认识是接龙数列的种类只有10种 0,1,2,3,4,5,6,7,8,9
//存储的是以i为结尾的最大子序列长度
int main()
{
    int res=0;
    int n;
    cin>>n;
    for(int i=0;i<n;++i)
    {
        string s;
        cin>>s;
       int l=s[0]-'0',r=s[s.size()-1]-'0';
       int f=max(1,g[l]+1);//求接上数列后于不接数列的最大值,
并且因为只有一种所以直接按照索引就能找个从而优化时间复杂度
       g[r]=max(g[r],f);//更新或者不更新
       res=max(res,f);//最终最大值的持续更新
    }
  
   
    cout<<n-res<<endl;
     
     
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值