zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    Gin 使用 websocket
    7天用Go从零实现Web框架Gee教程
    docker-compose 搭建 Redis Sentinel 测试环境
    关闭禁用 Redis 危险命令
    Redis Cluster 设置密码
    使用 twine 上传自己的 python 包到 pypi
    Redis 5.0.7 讲解,单机、集群模式搭建
    Redis 单机模式,主从模式,哨兵模式(sentinel),集群模式(cluster),第三方模式优缺点分析
    django 重写 mysql 连接库实现连接池
    编译安装httpd-2.4
  • 原文地址:https://www.cnblogs.com/ccryolitecc/p/14055817.html
Copyright © 2011-2022 走看看