一、题意
输入两个等长的字符串S、T,你的任务是用最少的操作步数把S变成T。
S由0、1、?构成,T由0、1构成。
可用的操作有:
- 把一个0变成1
- 把一个?变成0或1
- 交换两个字符的位置
输出最少步数。若没有办法则输出-1.
二、解析
这里的操作最关键的就是1如何变成0。我们用 x->y 表示x需要变成y。
实际上只可能通过交换 1->0 和一个 0->1 得到。因为交换 1->0 和 0->0 就会使得被交换得数对变成 1->0 这相当于没有解决问题。
因此我们统计 1->0 和 0->1 得个数,分别记为one2zero、zero2one。
若zero2one不够,则通过 ?->1 来进行补充,若这样还不够,则无解。若足够,则 交换 1->0 和 0->1 (一部分由?->1得到),然后剩余的 ?->x 就直接转变为 x->x (x=0,1)即可。
若zero2one充足,则无需补充,只要记得把多余的 0->1 变为 1->1 即可。
三、代码
#include <iostream> #include <string> #include <cmath> using namespace std; int kase; int main() { cin >> kase; for(int K = 1; K <= kase; K ++) { string a, b; cin >> a >> b; int one2zero = 0, zero2one = 0, none2one = 0, none2zero = 0; for(int i = 0; i < a.size(); i ++) if(a[i] != b[i]) { if(a[i] == '1') one2zero ++; else if(a[i] == '0') zero2one ++; else if(b[i] == '1') none2one ++; else none2zero ++; } int ans = none2one + none2zero; // ?总是要转变的,无论是否作为zero2zero的补充 if(zero2one + none2one >= one2zero) ans += max(one2zero, zero2one); else ans = -1; cout << "Case " << K << ": " << ans << endl; } }
四、归纳
- 思考题题目时要会抓重点进行突破。