Double or Noting - Google Codejam 2021 Round 1C第三题
You are given a starting non-negative integer S and an ending non-negative integer E. Both S and E are given by their binary representation (that is, they are given written in base 2). Your goal is to transform S into E. The following two operations are available to you:
Double your current value.
Take the bitwise NOT of your current value. The binary representation of your current value is taken without unnecessary leading zeroes, and any unnecessary leading zeroes produced by the operation are dropped. (The only necessary leading zero is the one in the representation of 0).
For example, by using the double operation, 6 becomes 12, 0 becomes 0, and 10 becomes 20. By using the NOT operation, 0 becomes 1, 1 becomes 0, 3=112 becomes 0, 14=11102 becomes 1, 10=10102 becomes 5=1012, and 5=1012 becomes 2=102. (X2 means the integer whose binary representation is X).
You can use these operations as many times as you want in any order. For example, you can transform S=100012 to E=1112 using the NOT operation first, then using the double operation twice, and then another NOT operation:
100012⟹NOT11102⟹×2111002⟹×21110002⟹NOT1112.
Determine the smallest number of operations needed to complete the transformation, or say it is impossible to do so.
题目大意:
你有两个01字符串S和E,你的任务是对S进行总次数尽量少的非(~)或者左移一位(<<1)的操作把它变成E。输出最少操作次数;若无法完成,输出"IMPOSSIBLE"。
思路分析:
今年Round 1三轮之中最简短也是最像算法题的压轴题了。对于这种题,相信对字符串手到擒来的同学们早已经轻车熟路了。由于该题对时间复杂度基本没什么要求(两个串都不长,最多只有100个字符),我们考虑直接枚举S和E的公共后缀(前缀),对于每一种长度的后缀直接模拟把S变成E的过程,最后取最小值即可。
模拟的方法也比较容易:连续的0或者1直接继续左移,否则非操作。如果这样最后得到的不是E,那说明保留当前后缀的状况下不可能。具体看代码:
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int T;
string inv(string a)//由于是字符串,建议自己写一个非运算
{
string res = "";
for (char c : a) {
if (c