第十六届蓝桥杯青少组C++省赛[2025.8.9]第二部分编程题(3、平衡奇偶位置的字母交换)

参考程序:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int minx(string s) {
    int n = s.size();
    int totalA = count(s.begin(), s.end(), 'A');   // 统计 'A' 的总数
    // 可行性:要想奇偶位 A 数相等,A 总数必须为偶数
    if (totalA % 2 == 1) return -1;

    int target = totalA / 2;                       // 目标:奇数位上的 A 个数
    int oddA = 0, evenA = 0;

    // 统计初始奇/偶位置上的 A 个数(i 从 0 开始,所以 i%2==0 表示 1-based 奇数位)
    for (int i = 0; i < n; ++i) {
        if (s[i] == 'A') {
            if ((i + 1) % 2 == 1) oddA++;          // 1-based 奇数位
            else evenA++;                          // 1-based 偶数位
        }
    }

    // 如果已经满足条件,0 次交换
    if (oddA == target) return 0;

    int swaps = 0;                                  // 记录最少交换次数

    // 从左到右扫描,遇到"放在多的一边的 A",就往前(右侧)找一个"对边的 B"来交换
    for (int i = 0; i < n; ++i) {
        if (oddA == target) break;                 // 够了就停

        // 情况1:当前是奇数位上的 A(1-based),而我们希望把奇数位 A 减少(oddA > target 时有效)
        if ((i + 1) % 2 == 1 && s[i] == 'A') {
            // 在 i 右侧寻找一个"偶数位上的 B"来交换(这样该 A 就跨到偶数位)
            for (int j = i + 1; j < n; j++) {
                if ((j + 1) % 2 == 0 && s[j] == 'B') {
                    swap(s[i], s[j]);              // 直接对调,等价于做了 (j-i) 次相邻交换
                    swaps += j - i;                // 累加交换步数
                    oddA--;                        // 该 A 已从奇数位移出
                    evenA++;                       // 偶数位 A 增加
                    break;                         // 处理下一个 i
                }
            }

        // 情况2:当前是偶数位上的 A,而我们希望把偶数位 A 减少(oddA < target 时有效)
        } else if ((i + 1) % 2 == 0 && s[i] == 'A') {
            // 在 i 右侧寻找一个"奇数位上的 B"来交换
            for (int j = i + 1; j < n; ++j) {
                if ((j + 1) % 2 == 1 && s[j] == 'B') {
                    swap(s[i], s[j]);
                    swaps += j - i;
                    oddA++;                        // 该 A 已跨到奇数位
                    evenA--;
                    break;
                }
            }
        }
    }

    // 若成功达到目标,返回累计交换次数;否则返回 -1(比如右侧找不到可交换的 B)
    if (oddA == target) return swaps;
    else return -1;
}

int main() {
    string s;
    cin >> s;
    cout << minx(s) << endl;
    return 0;
}