跳到主要内容
原文244 词数1 分钟

题解:AT_utpc2021_a Make UTPC

概述

每次操作交换字符串 S 中的两个字符,求让 S 至少包含一个连续子串 UTPC 所需的最少交换次数。枚举每个长度为 4 的起始位置 i,设 f(i) 为把该段改成 UTPC 的代价;对每个不匹配的位置,既可与段内字符交换,也可与段外字符交换(S 中必含 U、T、P、C,段内缺则段外有)。因只有 4 个字符,递归枚举所有交换方案取最小,再在所有位置上取最小值。

题意简述​

每次操作交换两个字符,使字符串 SS 包含至少 11 个连续子串 UTPC,求最小操作次数。

解题思路​

设 f(i)f(i) 为把 Si∼Si+3S_i\sim S_{i+3} 改为 UTPC 的操作次数,则最终答案为:

min⁡i=0∣S∣−4f(i)\min_{i=0}^{|S|-4}f(i)

在每个子串中,如果某个位置的字符不同,有两种解决方案:

  1. 和子串内的字符交换。
  2. 和子串外的字符交换。(SS 至少包含一个 U、T、P 和 C,如果子串内没有,则子串外一定有)

由于只有 44 个字符,可以递归枚举所有方案求出 f(i)f(i)。

参考代码​

501 Bcpp
#include <bits/stdc++.h>
using namespace std;

const char a[4]={'U','T','P','C'};
string s;
int f(int x,int k)
{
if(k>=4)return 0;
if(s[x+k]==a[k])return f(x,k+1);
int res=f(x,k+1)+1;
for(int i=k+1;i<4;i++)
{
if(s[x+i]!=a[k])continue;
swap(s[x+k],s[x+i]);
res=min(res,f(x,k+1)+1);
swap(s[x+k],s[x+i]);
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n>>s;
int ans=4;
for(int i=0;i<n-3;i++)ans=min(ans,f(i,0));
cout<<ans<<'\n';
return 0;
}