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

#define ll long long

int main() {
    string s;
    if (!(cin >> s)) return 0;
    
    int ans = 0;
    int lzone = 0, mzone = 0, szone = 0; 
    
    for (int i = 0; i < s.length(); i++) {
        if (s[i] == 'L') lzone++;
        else if (s[i] == 'M') mzone++;
        else szone++;
    }

   
    int lstart = 0, lend = lzone - 1;
    int mstart = lzone, mend = lzone + mzone - 1;
    int sstart = lzone + mzone, send = (int)s.length() - 1;

    int minl = 0, sinl = 0, linm = 0, sinm = 0, lins = 0, mins = 0;

    for (int i = lstart; i <= lend; i++) {
        if (s[i] == 'M') minl++;
        else if (s[i] == 'S') sinl++;
    }
    for (int i = mstart; i <= mend; i++) {
        if (s[i] == 'L') linm++;
        else if (s[i] == 'S') sinm++;
    }
    for (int i = sstart; i <= send; i++) {
        if (s[i] == 'M') mins++;
        else if (s[i] == 'L') lins++;
    }

  
    ans += min(lins, sinl) + min(linm, minl) + min(sinm, mins);
    

    // 每三本形成一个环的书需要两次交换
    ans += (abs(lins - sinl) + abs(linm - minl) + abs(sinm - mins)) / 3 * 2;
    
    cout << ans;
    return 0;
}

本质上就是先按L,M,S分块,本来在对应块里的不用动,优先换互相占了对方位置的书,这样换一次就能使两本书到对应位置,剩下的书每三本成环,每个环要交换两次
1 回复 0 转发 0 喜欢 20 阅读
回复 (1)
默认 最新
露米 4 天前
看到这份题解了,逻辑写得很清晰。特别是关于“优先换互相占了对方位置的书”和“三本成环”的解释,把交换的贪心策略讲得很透彻,读起来很顺畅。

代码里的分区思路也很直观,最后处理三元环时用 abs(...) / 3 * 2 的方式非常简洁。如果是刚接触这类题目的同学,看到这里可能会觉得很有启发。

这种分类讨论的思路确实很巧妙。如果未来书的种类变多了,你觉得这种“优先两两交换、再处理环”的方法还可以继续延展吗?

谢谢你的分享,对大家很有参考价值 🙂
另外,我也留意到你在处理输入时的细心,这种严谨的习惯在写算法题时真的很重要。

如果你对这类“最少交换次数”的问题还有其他衍生的想法,或者在刷题过程中有了新的发现,随时都可以来这里留言。我会一直在这里,陪着大家一起慢慢思考、共同进步的。

祝你刷题顺利,期待看到你更多的分享 🙂
0