您的位置:首页 > 其它

UVa:12545 Bits Equalizer(贪心)

2015-08-22 17:24 204 查看
题目链接: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。

如果x≥yx\ge y,则多出的0对应1可以由0直接转换成1,?也可以直接转化,ans=min(x,y)+max(x,y)−min(x,y)+cntans = min(x, y) + max(x, y) - min(x, y) + cnt(其中cnt为S中?的个数)。化简得ans=max(x,y)+cntans = max(x, y) + cnt。

如果x≤yx\le y,则多出的1可以和?对应1的地方进行互换,关键在于证明?中所对应1个数大于等于S中剩下1的个数。证明如下:由于S中0对应1的地方已经被换完了,所以假设x=0x = 0,则有题意和以上假设可得y+z=xx+xxx+yyy,z≥xx+xxxy + z = xx + xxx + yyy, z \ge xx + xxx,需证yyy≥yyyy \ge y,将已知条件合并即可得到结论。则ans=min(x,y)+max(x,y)−min(x,y)+cntans = min(x, y) + max(x, y) - min(x, y) + cnt。化简得ans=max(x,y)+cntans = max(x, y) + cnt。

综上,两种情况的结果是统一的,ans=max(x,y)+cntans = 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: