T1. 最佳路径
此题为 2021 年 6 月四级第一题原题,见 2021 年 6 月青少年软编等考 C 语言四级真题解析中的 T1。
T2. 邮票收集
此题为 2020 年 12 月四级第二题原题,见 2020 年 12 月青少年软编等考 C 语言四级真题解析中的 T2。
T3. 切割回文
阿福最近对回文串产生了非常浓厚的兴趣。
如果一个字符串从左往右看和从右往左看完全相同的话,那么就认为这个串是一个回文串。例如, a b c a a c b a \tt abcaacba abcaacba 是一个回文串, a b c a a b a \tt abcaaba abcaaba 则不是一个回文串。
阿福现在强迫症发作,看到什么字符串都想要把它变成回文的。阿福可以通过切割字符串,使得切割完之后得到的子串都是回文的。
现在阿福想知道他最少切割多少次就可以达到目的。例如,对于字符串 a b a a c c a \tt abaacca abaacca,最少切割一次,就可以得到 a b a \tt aba aba 和 a c c a \tt acca acca 这两个回文子串。
时间限制:1 s
内存限制:64 MB
- 输入
输入的第一行是一个整数 T ( T ≤ 20 ) T\ (T \le 20) T (T≤20),表示一共有 T T T 组数据。
接下来的 T T T 行,每一行都包含了一个长度不超过的 1000 1000 1000 的字符串,且字符串只包含了小写字母。 - 输出
对于每组数据,输出一行。该行包含一个整数,表示阿福最少切割的次数,使得切割完得到的子串都是回文的。 - 样例输入
3 abaacca abcd abcba
- 样例输出
1 3 0
- 提示
对于第一组样例,阿福最少切割 1 1 1 次,将原串切割为 a b a \tt aba aba 和 a c c a \tt acca acca 两个回文子串。
对于第二组样例,阿福最少切割 3 3 3 次,将原串切割为 a \tt a a、 b \tt b b、 c \tt c c、 d \tt d d 这四个回文子串。
对于第三组样例,阿福不需要切割,原串本身就是一个回文串。
思路分析
此题考查动态规划,属于基础题。
显然这里应该以序列长度为阶段,定义 f i f_i fi 表示前 i i i 个字符切割成回文串所需要的最少切割次数,于是我们可以枚举断点 k k k,当检测到 s [ k . . i ] s[k.. i] s[k..i] 为回文串时, f i = min { f k − 1 + 1 } f_i = \min\{f_{k-1}+1\} fi=min{fk−1+1}。初始状态为 f 1 = 0 f_1 = 0 f1=0,如果 s [ 1.. i ] s[1..i] s[1..i] 是回文串,则 f i = 0 f_i = 0 fi=0,其余均为 i n f inf inf,最终 f n f_n fn 即为答案。
/*
* Name: T3.cpp
* Problem: 切割回文
* Author: Teacher Gao.
* Date&Time: 2024/12/19 18:50
*/
#include <iostream>
#include <cstring>
using namespace std;
char s[1005] = " ";
bool check(int x, int y)
{
for (int i = x, j = y; i < j; i++, j--)
if (s[i] != s[j])
return false;
return true;
}
int main()
{
int t, f[1005];
scanf("%d", &t);
while (t--) {
scanf(" %s", s + 1);
int len = strlen(s) - 1;
memset(f, 0x3f, sizeof(f));
f[1] = 0;
for (int j = 1; j <= len; j++) {
if (check(1, j)) f[j] = 0;
for (int k = 2; k <= j; k++)
if (check(k, j))
f[j] = min(f[j], f[k-1] + 1);
}
printf("%d\n", f[len]);
}
return 0;
}
T4. 小球放盒子
此题为 2021 年 6 月四级第四 题原题,见 2021 年 6 月青少年软编等考 C 语言四级真题解析中的 T4。