蓝桥杯 — — 接龙数列
接龙数列
- 题源:0接龙数列 - 蓝桥云课
题目:
-
输入样例:
5 11 121 22 12 2023
-
输出样例:
1
分析:
-
首先观察评测用例规模, N N N 最大为 1 0 5 10^5 105,因此时间复杂度应该小于 O ( N 2 ) O(N^2) O(N2)。
-
题目大意是从一个数组中删除数字,使得剩下的数都是接龙数列(接龙数列:前一个数字的最后一位等于后一个数字的第一位),求出删除次数最少的次数。
-
转换一下题目含义,也就是求出最长的接龙数列,当接龙数列最长时,删除的次数一定最少。即:
最少次数 = 数列长度 − 最长接龙数列 最少次数 = 数列长度 - 最长接龙数列 最少次数=数列长度−最长接龙数列 -
求最长接龙数列,可以使用动态规划的思想,也就是任意规模的序列的最长接龙数列可以由其子序列的最长接龙数列递推过来。
-
设置数组 d p [ t ] dp[t] dp[t] 表示以 t t t 结尾的数字的最长接龙数列。首先要解决接龙数列的顺序问题,也就是保证前面接龙数列的各个数字的相对位置应该与原数列的相对顺序保持一致。接龙数列的顺序问题可以使用顺序遍历来解决,随着顺序遍历原数列来不断得到子序列的长度,从而保证了顺序的问题。
-
在本题中,对于每个数,最重要的是其头部数字和尾部数字,如:
2025
最重要的是2
和5
。因此对于每一个数字可以用字母 f f f 来表示其头部,用字母 t t t 来表示其尾部。可得递推公式:
d p [ t ] = m a x ( d p [ t ] + d p [ f ] + 1 ) dp[t] = max(dp[t] + dp[f] + 1) dp[t]=max(dp[t]+dp[f]+1)
递推公式解释:在顺序遍历的过程中,遍历到的每一个数只能添加到原始的某个接龙数列后面,因此每一个数就对应了两种状态:1. 添加该数; 2. 不添加该数
如果添加该数:
那么这个数一定添加在以 f f f 结尾的一个接龙数列的末尾,所以以这个数结尾的接龙数列 d p [ t ] dp[t] dp[t] 对应 d p [ f ] + 1 dp[f] + 1 dp[f]+1;如果不添加该数:
那么这个数结尾的接龙数列 d p [ t ] dp[t] dp[t] 还等于原来的 d p [ t ] dp[t] dp[t];
最后从 状态1 和 状态2 中选择更大的值作为以该数字尾部 t t t 结尾的最长的接龙数列
- 从 d p dp dp 数组中选取最大的值作为整个数列的最长的接龙数列,设为 s l e n slen slen 则最少删除的次数 = 数列长度 - slen。
代码:
// 数字接龙
#include<iostream>
#include<string>
using namespace std;
#define MAX_SIZE 100000 + 10int n;
int cnt[10];void solve() {cin>>n;string temp_s;int ans = 0;for(int i = 0;i < n;i ++) {cin>>temp_s;int front = temp_s[0] - '0';int tail = temp_s[temp_s.length() - 1] - '0';cnt[tail] = max(cnt[tail], cnt[front] + 1);ans = max(cnt[tail], ans);}cout<<n - ans<<endl;return ;
}int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t = 1;while(t --) solve(); return 0;
}