题目
题目思路
这是一个贪心题目,想到了是真牛逼,没想到是真难受啊!
我的想法是把这三种操作独立起来分别做,但是这样做的话就会多很多步数,他们之间的灵活性没有体现出来。
这个题目的话要抓住可以任意交换两个字符,所以会有以下的关系:
- 有 1 需要变成 0
- 有 0 需要变成 1
- 有 ? 需要变成 0
- 有 ? 需要变成 1
后三种都可以直接变化出来,第一种不能直接变化,所以首要任务就是把 1 -> 0 消去。
首先用 0- 1的情况与1-0的情况交换。
就会出现两种情况: ①0-1交换后还有,但是没有关系,可以直接变换出来。
②1-0交换后还有的话就得要 用 ? - 1 的情况去交换,(把?变为0,变成 0- 1的情况),如果交换完之后还有1-0的情况输出-1,无解了。
代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
string s, t;
int slove()
{
int ans = 0, s10 = 0, s01 = 0, q0 = 0, q1 = 0;
int sz = s.size();
_for (i, 0, sz) if (s[i] != t[i])
{
char& c = s[i];
if (c == '1') s10++;
if (c == '0') s01++;
if (c == '?')
{
if (t[i] == '0') q0++;
else q1++;
}
}
int x = min(s01, s10);
ans += x, s01 -= x, s10 -= x;
if (s10 > q1) return -1;
return ans += s10 + s01 + q0 + q1;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
for (int kase = 1; kase <= T; ++kase)
{
cin >> s >> t;
printf("Case %d: %d\n", kase, slove());
}
return 0;
}