uva12545 比特变换器(贪心)
输入两个等长的串S,T(长度小于100),其中S包含字符0,1,?,T中包含0和1。有三种操作:将S中的0变为1,?变为0或1,交换S中的任意两个字符。求将S变成T的最少步数。
首先考虑去掉问号。设S中1的个数为one1,T中1的个数为one2。在one1<one2的前提下,肯定是把问号填成与T中相同的数字更优。如果one1=one2,那么问号中只能填0。接着就是考虑将0变成1,相同的思路即可。最后等到one1=one2,统计S和T中不同的数字,计算出还要再走几步即可。
#include <cstdio>
#include <cstring>
using namespace std;
const int maxl=105;
int T, l1, l2, one1, one2, step;
char s1[maxl], s2[maxl];
int main(){
scanf("%d", &T);
for (int it=1; it<=T; ++it){
scanf("%s%s", s1, s2);
one1=one2=step=0; int tmp=0;
l1=strlen(s1); l2=strlen(s2);
for (int i=0; i<l1; ++i)
if (s1[i]=='1') ++one1;
for (int i=0; i<l2; ++i)
if (s2[i]=='1') ++one2;
if (l1!=l2||one1>one2){
printf("Case %d: -1\n", it);
continue; }
for (int i=0; i<l1; ++i)
if (s1[i]=='?'){ //用贪心法去除所有问号
s1[i]=s2[i];
if (s1[i]=='1') ++one1;
if (one1>one2) --one1, s1[i]='0';\
++step;
}
for (int i=0; i<l1; ++i) //用贪心法化0为1
if (one1<one2&&s1[i]=='0'&&s2[i]=='1'){
++one1; s1[i]='1'; ++step;
}
for (int i=0; i<l1; ++i) //统计不同之处
if (s1[i]!=s2[i]) ++tmp;
step+=tmp/2; //这是由于只有0和1
printf("Case %d: %d\n", it, step);
}
return 0;
}