zoukankan      html  css  js  c++  java
  • UVa 12545 Bits Equalizer (贪心)

    题意:给出两个等长的字符串,0可以变成1,?可以变成0和1,可以任意交换s中任意两个字符的位置,问从s变成t至少需要多少次操作。

    析:先说我的思路,我看到这应该是贪心,首先,如果先判断s能不能变成t,就计算t中的1和s中的1。

    然后算出t比s多多少1,然后先考虑把?变成1是最优的,如果不够就只能把0变成1,切不可把?变成1,因为这样要两步,

    不是最优,而把0变成1是一步。然后把剩下的?变成1(如果1还不够)或者是0(1够了)。最后是计算要交换的次数,

    这个只要统计不同的位置有多少即可,别忘了1可能还不够,这个也要算上,怎么算呢,想一下,先把0变成1,再交换,

    所以说是要先加上要变化的1,然后在不同位置中也加上,然后除以2.相加就是结果。

    然而我觉得自己写的太烂了,上网百度,看到大神们写的就是简洁明了。。。。

    是这么想的,首先交换是最优的,因为一次操作能满足两个,然后再去找1-0和?-1的进行交换,为什么呢?因为我们看s中的1是不是多了,

    如果少,没关系,可以直接把?变成1,如果多了就无解了,所以要比较这个。最后再加上?-0即可,这个只要一步。

    大神就是牛逼。

    代码如下:

    这是我的代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    const int maxn = 100 + 10;
    char s[maxn], t[maxn];
    
    int main(){
    //    freopen("in.txt", "r", stdin);
        int T;    cin >> T;
        for(int kase = 1; kase <= T; ++kase){
            scanf("%s %s", s, t);
            int n = strlen(s);
            int cnts1 = 0, cntt0 = 0, cnts0 = 0;//cnts1是s串中1的个数,同理其他的
            for(int i = 0; i < n; ++i){
                if('0' == t[i])   ++cntt0;
                if('0' == s[i])   ++cnts0;
                else if('1' == s[i])  ++cnts1;
            }
            int cntt1 = n - cntt0;//1的个数
            int cntss = n - cnts0 - cnts1;//?的个数
            int det = cntt1 - cnts1;//s和t差多少1
    
            printf("Case %d: ", kase);
            if(det < 0){  printf("-1
    "); continue; }//1太多了,把问号全改了都不够
    
            int cnt = 0;
            for(int i = 0; i < n; ++i)
                if(det && '?' == s[i] && t[i] == '1'){
                    ++cnt;  s[i] = '1'; --det;//把?变成1
                }
    
            for(int i = 0; i < n; ++i)//把0变成1
                if(det && '0' == s[i] && '1' == t[i]){
                    --det;  s[i] = '1';  ++cnt;
                }
    
            for(int i = 0; i < n; ++i){//把剩下的?变成0或1
                if(det && '?' == s[i]){  ++cnt;  s[i] = '1';  --det; }
                if(!det && '?' == s[i]){  ++cnt;  s[i] = '0';  }
            }
    
            int x = 0;
            for(int i = 0; i < n; ++i)//计算不同的数,
                if(s[i] != t[i]) ++x;
    
            cnt += det;//计算要要交换的次数
            cnt += (x + det)/ 2;
            printf("%d
    ", cnt);
        }
        return 0;
    }
    

    下面是我参考大神们的代码写的:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    const int maxn = 100 + 10;
    char s[maxn], t[maxn];
    
    int main(){
        int T;    cin >> T;
        for(int kase = 1; kase <= T; ++kase){
            scanf("%s %s", s, t);
            int n = strlen(s);
            int zero_one = 0, one_zero = 0, q_one = 0, q_zero = 0;
    
            for(int i = 0; i < n; ++i){
                if(s[i] == '0' && t[i] == '1')  ++zero_one;
                else if(s[i] == '1' && t[i] == '0')  ++one_zero;
                else if(s[i] == '?' && t[i] == '0')  ++q_zero;
                else if(s[i] == '?' && t[i] == '1')  ++q_one;
            }
    
            int cnt = 0;
            while(zero_one && one_zero){
                --zero_one;   --one_zero;
                ++cnt;
            }
    
            while(q_one && one_zero){
                --q_one;   --one_zero;
                cnt += 2;
            }
    
            if(one_zero)  cnt = -1;
            else  cnt += q_zero + zero_one + q_one;
    
            printf("Case %d: %d
    ", kase, cnt);
        }
        return 0;
    }
    
  • 相关阅读:
    MyBatis 知识点梳理
    SSH无密码登录的原理及配置
    Maven学习笔记
    阿里Java开发电话面试经历惨败
    Java生成验证码(二)
    Java生成验证码(一)
    Hibernate 知识点梳理
    数据结构线性表顺序表示 (二)
    replace tabs with the proper number of blanks
    数据结构线性表顺序表示 (三)
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5562502.html
Copyright © 2011-2022 走看看