试题 E:接龙数列
动态规划
d p [ i ] [ j ] dp[i][j] dp[i][j]: [ 0 , i ] [0,i] [0,i] 区间包含的整数中,以 j j j 为接龙数列末尾数字所能达到的最大长度。
我们从前往后依次遍历,遍历过程中有如下递推方程:
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ s [ i ] 的最高位数字 ] + 1 , d p [ i − 1 ] [ s [ i ] 的最低位数字 ] ) dp[i][j]=max(dp[i-1][s[i]的最高位数字]+1,dp[i-1][s[i]的最低位数字]) dp[i][j]=max(dp[i−1][s[i]的最高位数字]+1,dp[i−1][s[i]的最低位数字]).
此时的 d p dp dp 数组是一个二维数组,由于递推关系中用到的都是之前计算过的值,于是我们可以将 d p dp dp 数组降为一维数组 d p [ j ] dp[j] dp[j],表示遍历到当前整数以 j j j 为接龙数列末尾数字所能达到的最大长度。
此时的递推方程为: d p [ j ] = m a x ( d p [ 当前遍历的整数的最高位数字 ] + 1 , d p [ 当前遍历的整数的最低为数字 ] ) dp[j]=max(dp[当前遍历的整数的最高位数字]+1,dp[当前遍历的整数的最低为数字]) dp[j]=max(dp[当前遍历的整数的最高位数字]+1,dp[当前遍历的整数的最低为数字])
最终的结果为: n − m a x ( d p [ j ] ) ( 0 ≤ j ≤ n − 1 ) n-max(dp[j])\space(0\leq j\leq n-1) n−max(dp[j]) (0≤j≤n−1)
例如:对于输入 11 121 22 12 2023 11\space121\space22\space12\space2023 11 121 22 12 2023, d p [ 4 ] [ 1 ] = 2 , d p [ 4 ] [ 2 ] = 3 , d p [ 4 ] [ 3 ] = 4 dp[4][1]=2,dp[4][2]=3,dp[4][3]=4 dp[4][1]=2,dp[4][2]=3,dp[4][3]=4,最少要移去的整数个数为: 5 − 4 = 1 5-4=1 5−4=1。
注意:为了方便获得整数的最高位和最低位数字,我们用字符串存储整数!
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<int> dp(10);
int maxLen = 0; // 接龙数列最大值
int n; // 整数个数
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);
maxLen = max(maxLen, dp[b]);
}
cout << n - maxLen << endl;
return 0;
}