时间限制:1000ms 内存限制:65536kb OJ编号:1413
通过率:14/28 (50.00%) 正确率:14/79 (17.72%)
题目描述
叶姐要想哥赠送一串比特手链,这个手链由0和1组成。想哥买了手链B,无意间得知叶姐想要同样长度的手链A。想哥囊中羞涩,只能手工调整手链。他希望最少通过以下操作进行最少步骤把B变成A。注意:A != B
对于一个串S:
操作1——选择下标i,j,i != j:
·result = S[i] & S[j]
·S[i] = result & S[i]
·S[j] = result & S[j]
操作2——选择下标i,j,i != j:
·result = S[i] | S[j]
·S[i] = result | S[i]
·S[j] = result | S[j]
操作3——选择下标i,j,i != j:
·result = S[i] ^ S[j]
·S[i] = result ^ S[i]
·S[j] = result ^ S[j]
问想哥最少多少步能达成心愿。如果想哥无法达成心愿,输出-1。
输入
第一个数为数据组数T
接下来2T行,第2i - 1行为手链B,第2i行为手链A
输出
对于每组数据,输出一行,最少的步骤数。特别地,如果无法达成,输出-1。
输入样例
2
101
010
1111
1010
输出样例
2
-1
Hint
T<=5;
长度<=10^6;
AC代码(C++):
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
int T;
string A,B;
int main()
{
for(scanf("%d",&T);T--;){
cin>>B>>A;
int len=A.size();
int cnt1=0,cnt0=0;
int b1=0,b0=0;
for(int i=0;i<len;i++){
if(A[i]!=B[i]){
if(B[i]=='0')
cnt0++;
if(B[i]=='1')
cnt1++;
}
if(B[i]=='0')
b0++;
if(B[i]=='1')
b1++;
}
if(b0==len||b1==len){
printf("-1\n");
continue;
}
if(cnt0==cnt1)
printf("%d\n",cnt0);
else{
int maxcnt=max(cnt0,cnt1);
printf("%d\n",maxcnt);
}
}
}
思路:
这种题目,思路就是实体化变量。就是把题干里的s[i],s[j]用一个数对来实体化,这道题中就是数对(1,0)。经过实体化后可以发现且运算就是把1变0,把0变0;或运算就是把0变1,把1变1;异或运算就是把1变0,把0变1.这三种运算中异或运算是比较便捷的,因为只需要一次运算就能换两个数,另两个运算只能换1个数。所以要尽快转换,就要多用异或运算。
具体操作时,就是同时遍历两组字符串,遇上不相同的时候就记录,看B串中不同的是0还是1,cnt1,cnt0分别记录B串异于A串中1和0的个数。如果cnt0= =cnt1,那么把这些1和0用异或运算交换位置即可;若cnt0>cnt1,那么先进行cnt1次异或运算把1变成0,0变成1,然后剩下的cnt0-cnt1个0再用或运算换成1,总的运算次数为cnt0;cnt1>cnt0的情况同理。那么,我们就可以得到一个结论,如果可以实现转换,那么若cnt1!=cnt0,最少的转换次数为max(cnt1,cnt0),其实这个结论在cnt0= =cnt1时也是成立的。
那么哪种情况是不可以实现转换的呢?答案是若B为全0或者全1的情况下是无法转换的。可以通过分别计算B串中1和0的总个数并将之与B.size()进行比较,若相等则说为全1/0串。