题解:P12211 [蓝桥杯 2023 国 Python B] 翻转

一眼动态规划。

题目大意

\(n\) 个字符串,每个字符串都只有两位,我们要把它们拼接起来。如果字符串 \(a\) 的末位与字符串 \(b\) 的首位一样,我们在拼接的时候可以将这两个字符融合起来,使得长度变短。我们还可以将任意字符串翻转,最终目的是使得拼接过后的字符串长度尽可能短。

题目分析

我们定义一个二维数组 \(f\) 来表示每一阶段的答案。定义 \(f_{i,j}\) 为进行到第 \(i\) 个字符串时的最优解。\(j\) 只可能等于 \(1\) 或者 \(0\),分别表示当前字符串翻转和不翻转的情况。

接下来状态转移方程就很好推了。

对于 \(i-1\) 的不同状态,我们取其最小值并加上当前长度做为当前阶段的最优解。易得方程(假定字符串数组命名为 \(s\)):

\[f_{i,0}=\min(f_{{i-1},0}+2-[s_{{i-1},2}=s_{i,1}],f_{{i-1},1}+2-[s_{{i-1},1}=s_{i,1}]) \]

\[f_{i,1}=\min(f_{{i-1},0}+2-[s_{{i-1},2}=s_{i,2}],f_{{i-1},1}+2-[s_{{i-1},1}=s_{i,2}]) \]

AC 代码

记录

#include<bits/stdc++.h>
using namespace std;
char s[100005][5];
int n,f[100005][2];
int main()
{
	scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    f[1][0]=f[1][1]=2;//预处理
    for(int i=2;i<=n;i++)
    {
        f[i][0]=min(f[i-1][0]+(s[i-1][2]==s[i][1]?1:2),f[i-1][1]+(s[i-1][1]==s[i][1]?1:2));//状态转移方程
        f[i][1]=min(f[i-1][0]+(s[i-1][2]==s[i][2]?1:2),f[i-1][1]+(s[i-1][1]==s[i][2]?1:2));
    }
    printf("%d",min(f[n][0],f[n][1]));//输出答案
    return 0;
}
posted @ 2025-11-15 11:15  linruicong  阅读(4)  评论(0)    收藏  举报