📚 算法笔记:U535982 C-小梦的AB交换
1. 题目简述
- 输入 :一个长度为 2 n 2n 2n 的 A B AB AB 串(包含 n n n 个 A A A 和 n n n 个 B B B)。
- 操作 :每次可以选择任意两个位置 i , j i, j i,j 交换字符。
- 目标 :最少操作几次,使得字符串变为交替排列(即相邻字符不同)。
- 输出:最小交换次数。
2. 核心代码 (C++ 实现)
c++
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
int T;
if(!(cin >> T)) return; // 读入测试组数
while(T--)
{
ll n;
cin >> n;
string s;
cin >> s;
ll diff1 = 0, diff2 = 0;
// 核心:遍历 2*n 长度的串
for(int i = 0; i < 2 * n; i++)
{
// 构造两种目标模式:ABAB... 或 BABA...
char target1 = (i % 2 == 0) ? 'A' : 'B';
char target2 = (i % 2 == 0) ? 'B' : 'A';
// 统计当前串与两种目标的差异点个数
if(s[i] != target1) diff1++;
if(s[i] != target2) diff2++;
}
// 关键结论:一次交换可以同时修复两个错误位置
cout << min(diff1 / 2, diff2 / 2) << "\n";
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
solve(); // 内部已有 T 循环,直接调用
return 0;
}
3. 核心考点与注意事项
- 目标模式比对 :满足条件的字符串只有两种:
ABAB...和BABABA...。 - 任意交换带来的简化 :由于题目允许交换任意位置,我们不需要考虑移动距离,只需要关心"有多少个位置放错了"。
- 一次交换修两点 :因为 A 和 B 的总数固定。如果你有一个位置该放 A 却放了 B,必然在另一个位置该放 B 却放了 A。交换这两个放错的字符,可以同时修正 2 个差异位。
4. 易错点回顾 (My Mistakes)
1. 单引号 vs 双引号 (语法错误)
- 错误经历 :写成了
char target = "A";。- 纠正 :在 C++ 中,
char必须用单引号'A',双引号"A"是字符串常量,赋值给char会导致编译失败。2. 变量未初始化 (运行结果错误)
- 错误经历 :定义了
ll diff1, diff2;但没有写= 0。- 后果:局部变量初始值为随机值,导致计数结果变成天文数字。
- 纠正 :定义计数器时务必手动初始化为 0。
3. 循环范围与读入 (逻辑错误)
- 错误经历 :数组只开了
n长度,或者循环只跑了n次。- 纠正 :题目给定的是 n n n 对 AB,总长度是 2 × n 2 \times n 2×n,读入和循环都必须以此为准。
4. 输出位置错误 (多组数据逻辑)
- 错误经历 :将
cout放在了T循环之外。- 纠正 :这是多组测试数据,每处理完一个
n和s,就要立刻输出一个结果并换行。