C++,Lutece 1514 Little_Pro的driver朋友们和他的魔法

/*
Migrated from Lutece 1514 Little_Pro的driver朋友们和他的魔法
Description
Littlte_Pro像很多学生一样生活在清水河畔,同时周围也住着大量的driver朋友们,总共有 n个drivers和Little_Pro生活在清水河畔,
所有的driver都被Little_Pro用特殊的魔法祝福过,所以这些driver只能是good driver 或者 bad driver 这2个对立事件中的一个。

Littlte_Pro 是一个聪明的小司机。有一天,他想让所以的 drivers朋友们排成一个队列。然而作为一个与众不同的小司机,
他想让这些队列的good driver、baddriver交替出现,从而为我校交通事业做出了巨大的贡献。
我们的 Little_Pro 同时也是一位大魔法师. 每一次施法,他可以在一瞬间交换2个driver的在队列中的位置, 
或者改变driver叔叔的性质(把一个good driver 变成 bad driver 或者把一个bad driver 变成 good driver),
无论是无所畏惧的Zhong大司机title,还是三金在手的cx大司机,Littlte_Pro都可以用魔法瞬间把他们变成坏司机 (偷笑),搞怪结束了再把他们又变回来。

虽然Little_Pro是一位无所不能的小司机,但还是请你帮忙找到最少的施法次数,
从而使这些driver朋友们在队列中good driver、bad driver交替出现。

test 1即样例,如果出现本机通过样例,提交出现wrong answer on test 1的情况,
请检查在gets或者scanf("%c")之前是否已经使用getchar()将上一行的空格吸收。

Input
第一行输入一个 integer n (1 ≤ n ≤ 100,000) — 表示drivers的数量.

第二行输入一个包含n个元素的字符串, 其中包括字符'1' 和字符 '0',其中’1’ 代表 bad driver、 ‘0’ 代表 good driver.

Output
输出一个 integer — Little_Pro 需要的最少的施法次数,从而使这些driver在队列中good driver、bad driver交替出现。
*/

// #include <iostream>
// #include <string>
// #include <vector>
// int main(){
//     int driverNum;std::cin>>driverNum;
//     std::string driversStates;std::cin>>driversStates;
//     //0101... or 1010...
//     //最终想要的结果是形如010101...或101010...的字符串,即01或10交替出现
//     //统计初始字符串与目标字符串的差异,分别统计初始字符串中错误的0和错误的1的数量
//     //对较大的错误数量,多出的那部分必须要进行改变, 与较小的错误数量相等的部分进行交换
//     //例如若有5个错误的0,3个错误的1,则需交换3次0和1,再将多出的两个0变为1,需要总共5次操作
//     //因此对一个目标字符串, 需要的操作次数是max(错误的0数量,错误的1数量)
//     //对于0101...和1010...两种情况,分别统计,取较小的操作次数
//     int pattern01_evenErrors = 0,pattern01_oddErrors = 0;
//     int pattern10_evenErrors = 0,pattern10_oddErrors = 0;
//     for(int i = 0;i<driverNum;++i){
//         //      00,     11,     01,         10
//         //0101  0:+1    1:+1    +0          1:+1,0:+1
//         //1010  0:+1    1:+1    1:+1,0:+1   +0
//         if(i%2==0){
//             if(driversStates[i]!='0'){
//                 pattern01_evenErrors++;
//             }
//             if(driversStates[i]!='1'){
//                 pattern10_evenErrors++;
//             }
//         }else{
//             if(driversStates[i]!='1'){
//                 pattern01_oddErrors++;
//             }
//             if(driversStates[i]!='0'){
//                 pattern10_oddErrors++;
//             }
//         }
//     }
//     int opsPattern01 = std::max(pattern01_evenErrors,pattern01_oddErrors);
//     int opsPattern10 = std::max(pattern10_evenErrors,pattern10_oddErrors);
//     std::cout<<std::min(opsPattern01,opsPattern10)<<std::endl;
// }



// xf的解法
#include <iostream>
#include <string>
#include <algorithm>

int main( ) {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    int num0 = 0, num1 = 0;//统计0和1的数量
    int num11 = 0, num00 = 0;//偶数位上1和0的数量
    for (int i = 0; i < n; i++) {
        if (s[i] == '1') {
            num1++;
        }
        else {
            num0++;
        }
        if (i % 2 == 0) {
            if (s[i] == '1') {
                num11++;
            }
            else {
                num00++;
            }
        }
    }
    // T0 : 正确的0的数量, F0 : 错误的0的数量
    // T1 : 正确的1的数量, F1 : 错误的1的数量
    // num0 = T0 + F0, num1 = T1 + F1
    // 0101.. : num11 = F1, num00 = T0
    // 1010.. : num11 = T1, num00 = F0

    // 0101..,
    //   num0 = T0 + F0, num1 = T1 + F1
    //   num11 = F1, num00 = T0
    //   01..010 odd length,  (n+1)/2 = T0 + F1, n/2 = T1 + F0
    //   01..01  even length, (n+1)/2 = T0 + F1, n/2 = T1 + F0
    // 1010..,
    //   num0 = T0 + F0, num1 = T1 + F1
    //   num11 = T1, num00 = F0
    //   10..101 odd length,  (n+1)/2 = T1 + F0, n/2 = T0 + F1
    //   10..10  even length, (n+1)/2 = T1 + F0, n/2 = T0 + F1

    // 01_T0 = 10_F0, 01_F0 = 10_T0, 01_T1 = 10_F1, 01_F1 = 10_T1

    //答案应是min(max01(F0,F1),max10(F0,F1))

    // 0101...
        // F1 = num11, num1 - num11 = T1, n/2 - T1 = F0
        // max(F1,F0) = max(num11,n/2 - (num1-num11))
    // 1010..
        // F0 = num00, num0 - num00 = T0, n/2 - T0 = F1 
        // max(F0,F1) = max(num00,n/2 - (num0-num00))
    std::cout<<std::min(
        std::max(num11,n/2 - (num1 - num11)),
        // 0101.. , max(F1,F0) = max(num11,n/2 - (num1-num11)) = max(F1,F0)
        // 1010.. ,max(num11,n/2 - (num1-num11)) = max(T1,T0+F1 - T1-F1+T1) = max(T1,T0)
        std::max(num00,n/2 - (num0 - num00))
        // 0101.., max(num00, n/2 - (num0-num00)) = max(T0,T1+F0-T0-F0+T0) = max(T0,T1))
        // 1010.., max(F0,F1) = max(num00,n/2 - (num0-num00))  = max(F0,F1)

        //如果目标是0101..,则输出的是min(max(01_F1,01_F0),max(01_T0,01_T1)) = min(max(01_F1,01_F0),max(10_F0,10_F1)) = min(max01(F0,F1),max10(F0,F1))
        //如果目标是1010..,则输出的是min(max(10_T1,10_T0),max(10_F0,10_F1)) = min(max(01_F1,01_F0),max(10_F0,10_F1)) = min(max01(F0,F1),max10(F0,F1))

    )<<std::endl;
    // std::cout << std::min(
    //     std::max( 
    //         (n + 1) / 2 - num11 + std::max(0, num1 - (n + 1) / 2),
    //         // (n+1)/2 - num11 : T0 or F0,
    //         // num1 - (n+1)/2 : T1-T0 or F1-F0
    //         std::max(n / 2 - num0, num00) 
    //         // n/2 - num0 : T1-T0 or F1-F0
    //         // num00 : T0 or F0

    //         //0101... max(T0+max(0,T1-T0), max(T1-T0,T0))
    //         //1010... max(F0+max(0,F1-F0), max(F1-F0,F0))
    //     ), 
    //     std::max(
    //         (n + 1) / 2 - num00 + std::max(num0 - (n + 1) / 2, 0), 
    //         std::max(n / 2 - num1, num11)
    //     )
    // ) << std::endl;
}
posted @ 2025-03-19 21:44  Kazuma_124  阅读(89)  评论(0)    收藏  举报