UVa:12545 Bits Equalizer(贪心)

9 篇文章 0 订阅

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=845&page=show_problem&problem=3990

题意:输入两个等长(长度不超过100)的串S和T,其中S包含字符0,1,?,但T只包含0和1。你的任务是用尽量少的步数把S变成T。每步有3种操作:把S中的0变成1;把S中的“?”变成0或者1;交换S中任意两个字符。例如:01??00经过3步可以变成001010(方法是先把两个问号变成1和0,再交换两个字符)。(本段摘自《算法竞赛入门经典(第2版)》)

分析:
       直觉是采用贪心。策略如下:由于S中0可以转换成1,而1不能转换成0,所以首先统计S中?和1的个数cnt1,以及T中0的个数cnt2,如果cnt1小于cnt2,很明显无法转化成功,直接输出-1。其他情况都可以转化成功。
       对于可以转换的情况,从贪心的角度来看,将S中的两个字符交换位置最多可以使2个字符到达正确位置,而其他操作只能有一个,因此优先考虑此操作。由于S和T中位置相同且字符也相同的不需要转换,因此只考虑不相同的。设S中0的个数为x,1的个数为y,?的个数为z,T中与S的1对应的0的个数为xx,与S中0对应的1的个数为yy,与S中?对应的0和1的个数分别为xxx和yyy。
      如果 xy ,则多出的0对应1可以由0直接转换成1,?也可以直接转化, ans=min(x,y)+max(x,y)min(x,y)+cnt (其中cnt为S中?的个数)。化简得 ans=max(x,y)+cnt
     如果 xy ,则多出的1可以和?对应1的地方进行互换,关键在于证明?中所对应1个数大于等于S中剩下1的个数。证明如下:由于S中0对应1的地方已经被换完了,所以假设 x=0 ,则有题意和以上假设可得 y+z=xx+xxx+yyy,zxx+xxx ,需证 yyyy ,将已知条件合并即可得到结论。则 ans=min(x,y)+max(x,y)min(x,y)+cnt 。化简得 ans=max(x,y)+cnt
     综上,两种情况的结果是统一的, ans=max(x,y)+cnt

代码:

#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <set>
#include <string>

using namespace std;

const int maxn = 1005;

int T, ans, cnt, cnt1, cnt2, x, y, l;
string s, t;

int main()
{
    scanf("%d", &T);
    for (int C = 0; C < T; ++C)
    {
        ans = 0;
        cnt = 0;
        cnt1 = 0;
        cnt2 = 0;
        x = 0;
        y = 0;
        cin >> s >> t;
        l = s.size();
        for (int i = 0;i < l; ++i)
        {
            if (s[i] == '?')
                ++cnt;
            if (s[i] != '1')
                ++cnt1;
            if (t[i] == '0')
                ++cnt2;
            if (s[i] == '0' && t[i] == '1')
                ++x;
            if (s[i] == '1' && t[i] == '0')
                ++y;
        }
        if (cnt1 < cnt2)
            ans = -1;
        else
            ans = max(x, y) + cnt;
        printf("Case %d: %d\n", C + 1, ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值