• 【Gym102823H】Hamming Distance


    Gym https://codeforces.com/gym/102823/problem/H


    01

    先贴一个错误的贪心

    Wrong answer on test 1

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define _4v system("pause");
    #define zsbd return 0;
    int t, len, A_as, B_as, dif;
    int last_moda, first_modc;
    string str_A, str_B, str_C;
    int main()
    {
        scanf("%d", &t);
        str_C.reserve(12345678);
        for (int cas = 1; cas <= t; ++cas)
        {
            printf("Case %d: ", cas);
            cin >> str_A >> str_B;
            len = str_A.length();
            A_as = B_as = 0;
            for (int i = 0; i < len; ++i)
            {
                str_C[i] = 'a';
                A_as += (str_A[i] == 'a');
                B_as += (str_B[i] == 'a');
            }
            if (A_as < B_as)   
            {
                for (int i = 0; i < len; ++i) swap(str_A[i], str_B[i]);
                swap(A_as, B_as);
            }
            dif = A_as - B_as;
            int i = len;
            last_moda = first_modc = 0;
            while (dif)
            {
                --i;
                if (str_A[i] == str_B[i] || str_B[i] == 'a') continue;
                if (str_A[i] == 'a')
                {
                    if (str_B[i] == 'b')
                    {
                        if (dif > 1)
                        {
                            str_C[i] = 'b';
                            dif -= 2;
                            if (!first_modc) first_modc = i;
                            continue;
                        }
                        else
                        {
                            str_C[i] = 'b';
                            if (first_modc)
                            {
                                if (str_B[first_modc] == 'b')
                                {
                                    if (last_moda) str_C[last_moda] = 'a';
                                    else str_C[first_modc] = 'c';
                                }
                                else
                                {
                                    if (last_moda <= first_modc) str_C[last_moda] = 'a';
                                    else str_C[first_modc] = 'b';
                                }
                            }
                            else
                            {
                                str_C[i] = 'c';
                            }
                            dif = 0;
                        }
                    }
                    else
                    {
                        if (dif > 1)
                        {
                            str_C[i] = str_B[i];
                            dif -= 2;
                            if (!first_modc) first_modc = i;
                            continue;
                        }
                        else
                        {
                            str_C[i] = 'b';
                            dif = 0;
                        }
                    }
                }
                else
                {
                    str_C[i] = str_B[i];
                    --dif;
                }
                last_moda = i;
            }
            for (int i = 0; i < len; ++i)
            {
                putchar(str_C[i]);
            }
            putchar('
    ');
        }
        //
        _4v zsbd
    }
    

    02

    再给出一种错误的做法

    这道题应该要做一点更加仔细的分类讨论
    一开始先全部填上 a
    考虑一下都有怎样的情况可以改变汉明距离差值

    A B
    1 a b
    2 a *
    3 * a
    4 b a
    5 x y

    (1) 变成c减一,变成b减二
    (2) 变成b减一,变成*减二
    (3) 变成b加一,变成*加二
    (4) 变成c加一,变成b加二
    (5) 变成x加一,变成y减一
    那么实际上怎么做好一点呢
    首先从后往前扫,尽量减二
    最后一次假如刚好是减二而且差值不够用了
    假如是情况2那不用多考虑直接变成减一

    假如是情况1
    那先变成减二,然后在这里停止,往后扫
    对于第一个碰到的,属于情况 1~5 之内某一种的位置
    如果把它修改后字典序将要变小的话:
    1..假如第一个碰到的是之前减二过的就变成减一
    2..假如是之前减一过的就变成减零
    3..假如是之前没操作过的就给它加一。
    (由于前面尽力减了,所以不可能说往后扫的时候加二减一加二减一。)
    对于更换后会使字典序变大的操作,那就再从后往前扫一次,把最后面的那一个给换了。
    如果这些情况都碰不到,那就直接把停住的那个位置从减二直接变成减一。

    然而这也是错误的

    我暂且把代码贴在这里,还没有对拍并且过不了
    可能是我代码写错了也可能是这个办法行不通

    Wrong answer on test 1


    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int t;
    string A, B, C;
    int n, aA = 0, aB = 0, dif, cut = -1;
    int main()
    {
        cin >> t;
        C.resize(1919810);
        for (int cas = 1; cas <= t; ++cas)
        {
            printf("Case %d: ", cas);
            cin >> A >> B;
            n = A.length();
            aA = aB = 0;
            cut = -1;
            for (int i = 0; i < n; ++i)
            {
                C[i] = 'a';
                aA += (A[i] == 'a');
                aB += (B[i] == 'a');
            }
            if (aA < aB) 
            {
                for (int i = 0; i < n; ++i) swap(A[i], B[i]);
                swap(aA, aB);
            }
            dif = aA - aB;
            for (int i = n - 1; i >= 0 && dif; --i)
            {
                if (A[i] == B[i] || B[i] == 'a') continue;
                if (A[i] == 'a')
                {
                    if (B[i] == 'b')
                    {
                        if (dif > 1)
                        {
                            C[i] = 'b';
                            dif -= 2;
                        }
                        else
                        {
                            cut = i;
                            C[i] = 'b';
                            dif = 0;
                        }
                    }
                    else
                    {
                        if (dif > 1)
                        {
                            C[i] = B[i];
                            dif -= 2;
                        }
                        else
                        {
                            C[i] = 'b';
                            dif = 0;
                        }
                    }
                    continue;
                }
                C[i] = B[i];
                --dif;
            }
            if (cut >= 0)
            {
                bool suc = false;
                for (int i = cut + 1; i < n; ++i)
                {
                    if (A[i] == B[i]) continue;
                    if (A[i] == 'a')
                    {
                        // -2 to -1
                        if (B[i] == 'b') C[i] = 'c'; 
                        else continue;
                    }
                    else if (B[i] == 'a')
                    {
                        // 0 to +1
                        continue;
                    }
                    else
                    {
                        // -1 to 0
                        C[i] = 'a';
                    }
                    suc = true;
                    break;
                }
                if (!suc)
                for (int i = n - 1; i > cut; --i)
                {
                    if (A[i] == B[i]) continue;
                    if (A[i] == 'a')
                    {
                        // -2 to -1
                        if (B[i] == 'b') C[i] = 'c'; 
                        else continue;
                    }
                    else if (B[i] == 'a')
                    {
                        // 0 to +1
                        C[i] = (A[i] == 'b') ? 'c' : 'b';
                    }
                    else
                    {
                        // -1 to 0
                        continue;
                    }
                    suc = true;
                    break;
                }
                if (!suc)
                {
                    C[cut] = 'c';
                }
            }
            for (int i = 0; i < n; ++i)
            {
                putchar(C[i]);
            }
            putchar('
    ');
        }
        //
        // system("pause");
        return 0;
    }
    

    03

    换一种思路,一开始不要先全部填 a
    为啥?
    假如不确定的话,新填一个数最多只会让汉明距离差值变化 ±1
    先填上 a 没有任何意义还可能让这种变化变大,反正就是更麻烦了
    。。。

    所以,记录一下往后有多少个位置两串的字符不同
    一边走一边数一数现在到两串汉明距离的差有多大了,控制一下。
    如果没有问题就直接a
    α:

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int t;
    string A, B, C;
    int len, cur_dif;
    int sum[10010];
    char ch;
    char lower(const char &a, const char &b)
    {
        for (char t = 'a'; t <= 'z'; ++t)
        {
            if (t != a && t != b) return t;
        }
    }
    int main()
    {
        cin >> t;
        C.resize(1919810);
        for (int cas = 1; cas <= t; ++cas)
        {
            printf("Case %d: ", cas);
            cin >> A >> B;
            len = A.length();
            sum[len] = cur_dif = 0;
            for (int i = len - 1; i >= 0; --i)
            {
                sum[i] = sum[i + 1] + (A[i] != B[i]);
            }
            for (int i = 0; i < len; ++i)
            {
                if (A[i] == B[i])
                {
                    C[i] = 'a';
                    continue;
                }
                if (abs(cur_dif) < sum[i + 1])
                {
                    C[i] = 'a';
                    if (A[i] == 'a') ++cur_dif;
                    if (B[i] == 'a') --cur_dif;
                }
                else
                {
                    ch = lower(A[i], B[i]);
                    if (!cur_dif) C[i] = ch;
                    else if (cur_dif > 0)
                    {
                        if (ch < B[i] && cur_dif == sum[i + 1]) C[i] = ch;
                        else C[i] = B[i], --cur_dif;
                    }
                    else
                    {
                        if (ch < A[i] && cur_dif == -sum[i + 1]) C[i] = ch;
                        else C[i] = A[i], ++cur_dif;
                    }
                }
            }
            for (int i = 0; i < len; ++i) putchar(C[i]);
            putchar('
    ');
        }
        //
        // system("pause");
        return 0;
    }
    
  • 相关阅读:
    龙井和碧螺春的功效与作用
    064 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 无参带返回值方法
    063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法
    062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用
    061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结
    060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序
    059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环
    058 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 05 案例:求数组元素的最大值
    057 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 04 案例:求整型数组的数组元素的元素值累加和
    056 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 03 一维数组的应用
  • 原文地址:https://www.cnblogs.com/ccryolitecc/p/14055817.html
Copyright © 2020-2023  润新知