当前位置: 首页 > news >正文

算法日记34:14届蓝桥C++B接龙数列(动态规划DP)

一、题目:

在这里插入图片描述

二、题解一:朴素动态规划 O ( n 2 ) O(n^2) O(n2) 50 50 50%样例

1、解题思路

1)通过观察题目我们发现:题目意思为从序列中最少删除多少数,可以使得接下来的序列是接龙序列

2)因此我们可以将其转化为求最长的接龙子序列的长度 x x x,用 ( n − x ) (n-x) (nx)即是答案

3)接着题目就变成了典型的 D P DP DP问题:求解最长接龙子序列

2、动态规划做题步骤

1)重述问题:

  • 找一个最长的接龙子序列

2)找到最后一步:

  • 选择了某个数 a [ x ] a[x] a[x],作为接龙序列的最后一位

3)去掉最后一步骤,原问题变成了什么?(如果可以就尝试用去掉最后一步的状态推导->最后一步

  • ( 1 − > x − 1 ) (1->x-1) (1>x1)中,找最长的接龙子序列

原问题的答案=(1~x-1)中,找最长的接龙子序列的长度+1(且最后一位需要满足条件)

4)考虑边界

3、关键代码解析

int col(int x)  //取出其第一位
{
  int temp=0;
  while(x)
  {
    temp=x%10;
    x/=10;
  }
  return temp;
}

//遍历找最后一位
  for(int i=1;i<=n;i++)
  {
    int last=col(a[i]); //拿出其第一位
    dp[i]=1;  //默认长度为1
    for(int j=1;j<=i-1;j++) //从1~x-1中找倒数第二位
    {
      if(a[j]%10==last) dp[i]=max(dp[i],dp[j]+1);	//判断是否由倒数第二位推出
    }
  }
  int res=-1;
  for(int i=1;i<=n;i++) res=max(res,dp[i]);
  cout<<n-res<<'\n';

三、题解二:DP优化 O ( n ) O(n) O(n)

通过观察我们发现:最长接龙子序列的最后一位仅仅是(1~10),且它具有后效性
因此我们可以考虑简化dp数组

1、解题思路

1)我们可以令dp[d]为以d为结尾的最长接龙子序列的长度

  • 比如dp[1]表示以1为结尾的最长接龙子序列的长度

2)现在我们枚举到了a[i]这个数,它的最高位是x,最后一位是y

在这里插入图片描述

3)此时我们发现,这个值有且只有两种情况

  • 找到一个以x为结尾的一个序列,将其接上去,这样原本结尾是x的序列,就变成了结尾是y的序列(此时dp[y]=dp[x]+1)
  • 或者不接上去,那么dp[y]的值也不会受其影响(也就意味着此时有以y为结尾的已经更优了)(此时dp[y]不变)

4)因此状态转移方程应该为: d y [ y ] = m a x ( d p [ y ] , d p [ x ] + 1 ) dy[y]=max(dp[y],dp[x]+1) dy[y]=max(dp[y],dp[x]+1)

2、关键代码解析:

  • 1# 获取一个数字的最高位与最低位数
  • 2#选择接入以first为结尾,使得以end为结尾 + 1 +1 +1
  • 3# 不接入,以end为结尾的已经优于以fir为结尾的
 //遍历找最后一位
  for(ll i=1;i<=n;i++)
  {
    ll first=col_fir(a[i]); //拿出其第一位和最后一位
    ll end=a[i]%10;

    //选择接入以first为结尾,使得以end为结尾+1 /
    //不接入,以end为结尾的已经优于以fir为结尾的
    dp[end]=max(dp[end],dp[first]+1); 
  }
  ll res=-1;
  for(ll i=1;i<=9;i++) res=max(res,dp[i]);
  cout<<n-res<<'\n';

3、完整代码解析:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N=2e5+7;
ll a[N];
ll dp[17];//表示以i为结尾在最长序列

ll col_fir(ll x)  //取出其第一位
{
  ll temp=0;
  while(x)
  {
    temp=x%10;
    x/=10;
  }
  return temp;
}

void solve()
{
  ll n;cin>>n;
  for(ll i=1;i<=n;i++) cin>>a[i];
  //通过
  //题目意思为从序列中最少删除多少数,可以使得接下来的序列是接龙序列
  //因此我们可以将其转化为求最长的接龙子序列的长度x,(n-x)即是答案

  //遍历找最后一位
  for(ll i=1;i<=n;i++)
  {
    ll first=col_fir(a[i]); //拿出其第一位和最后一位
    ll end=a[i]%10;

    //选择接入以first为结尾,使得以end为结尾+1 /
    //不接入,以end为结尾的已经优于以fir为结尾的
    dp[end]=max(dp[end],dp[first]+1); 
  }
  ll res=-1;
  for(ll i=1;i<=9;i++) res=max(res,dp[i]);
  cout<<n-res<<'\n';
}  

int main()
{
  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  int _=1;
  while(_--) solve();
  return 0;
}

相关文章:

  • 安全见闻之网络安全新兴术语
  • ThreadLocal
  • 马尔科夫不等式和切比雪夫不等式
  • 为AI聊天工具添加一个知识系统 之138 设计重审 2 文章学 之2
  • Linux基础 IO 和文件
  • 期权交易的优势和缺点是什么?
  • 斗地主小游戏
  • 运算放大器LM358的简单应用
  • LeetCode第78题_子集
  • ubuntu打包 qt 程序,不用每次都用linuxdeployqt打包
  • mybatisplus 开发流程
  • 1236 - 二分查找
  • jenkins配置连接k8s集群
  • LeetCode和为k的字数组(560题)
  • 【hello git】git 扫盲(add、commit、push、reset、status、log、checkout)
  • C语言学习笔记:初阶指针
  • 在 Maven 中使用 <scope> 元素:全面指南
  • “深入浅出”系列之Linux篇:(10)基于C++实现分布式网络通信RPC框架
  • 软件开发工程师与AI工具
  • MySQL字段内容加解密使用性能验证
  • 免费下载微信/seo人人网
  • 什么网站做新闻更好/seo自然排名
  • 做网站百度收录/谷歌搜索网址
  • 网站建设论文 优帮云/牡丹江网站seo
  • 粮食局网站建设报告/互联网推广的方式
  • 邯郸企业网站制作/贴吧aso优化贴吧