对于一个长度为 K的整数数列:A1,A2,…,AK我们称之为接龙数列当且仅当 Ai 的首位数字恰好等于 Ai−1的末位数字 (2≤i≤K)。
例如 12,23,35,56,61,1112,23,35,56,61,11 是接龙数列;12,23,34,5612,23,34,56 不是接龙数列,因为 56 的首位数字不等于 34 的末位数字。
所有长度为 1 的整数数列都是接龙数列。
现在给定一个长度为 N 的数列 A1,A2,…,AN请你计算最少从中删除多少个数,可以使剩下的序列是接龙序列?
第一行包含一个整数 N。
第二行包含 N个整数 A1,A2,…,AN。
输出格式
一个整数代表答案。
数据范围
对于 20% 的数据,1≤N≤20。
对于 50% 的数据,1≤N≤10000。
对于 100% 的数据,1≤N≤105,1≤Ai≤109。所有 Ai保证不包含前导 0。
输入样例:
5
11 121 22 12 2023
输出样例:
1
样例解释
删除 22,剩余 1,121,12,2023是接龙数列。
//定义dp[i][j]为前i个数中, 以数字j结尾的最长接龙数列的长度。
设第i个数的首位数字是a, 末位数字是b。 则dp[i]中相对于dp[i−1]
可能发生变化的只有dp[i][b], 因为第i个数只可能加到一个以a结尾的接龙数列中, 使得这个接龙数列长度加1并且结尾数字变成b.
dp[i][b] = max(dp[i - 1][b], dp[i - 1][a] + 1)// 状态转移方程
直接优化一维
#include <iostream>
#include<cstring>
using namespace std;
int dp[10];
int main () {
int n, mx = 0;
cin >> n;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
int a = s[0] - '0', b = s.back() - '0';
dp[b] = max(dp[b], dp[a] +1);
mx = max(mx, dp[b]);
}
cout << n - mx << endl;
return 0;
}