参考了https://blog.csdn.net/catglory/article/details/47188949

最后推出来操作的个数为问号的个数 加上 同一位置上S串为0而T串为1的位置数量

与 同一位置上S串为1而T串为0的位置数量的最大值。

也就是max(ans1 + ans2) + que (que为问号总数, 而ans1和ans2意义如上)

这个公式应该是众多博客里面最简单的了, 让我一步一步推给你看

首先判断可不可行, 如果S串1大于T串中1的个数那么就永远不行

因为S串中1的个数只能增加(0变成1或者问号变成1), 不能减少。

所以导致了S串中1的个数永远大于T串中1的个数, 自然不管怎么变永远不能相等

然后考虑怎么变

首先问号变成数字最多可以消去1个差异, 0变成1也是最多消去1个差异, 而交换可以消除两个差异

所以尽量交换, 能交换就交换。

所以第一步就是先尽量交换, 问号先不理它。

交换的操作数怎么求?

交换的时候把0和1交换位置使得相同, 也就是说要“配对”, 也就是一对同一位置上S串是0而T

串是1和同一位置上S串是1而T串是0的两个位置, 这个时候可以交换, 然后位置就匹配上了。

所以我们就要找这样子有几对。

显然, 我们可以求出同一位置上S串是0而T串的位置数ans1, 和同一位置上S串是1而T串为0的位置数

ans2, 那么既然要“配对”, 那么对数就是两者的最小值,多余的后面再处理。

也就是对数 = min(ans1 + ans2)

好了, 交换完了之后,差异有两个, 一个是问号, 一个是交换下来多出的位置。

问号的操作数到最后会加上。

多出的位置要不全是S串为0, T串为1, 要不全是S串为1, T串为0 要不刚好匹配完。

(1)刚好匹配完(ans1 = ans2), 那就把问号全部变成与T串该位置的数字一样就可以了。

那么此时ans1 = ans2, 也就是配对消耗的操作 = min(ans1 + ans2) = ans1(或ans2, 无所谓)

所以总操作数= 配对消耗的操作+问号变化的操作 = ans1 + que(que为问号数)

显然开头那个式子是可以使用这种情况的, 也就是max(ans1 + ans2) + que = ans1 + que

(2)如果匹配完多余的是同一位置上S串为0T串为1(ans1 >ans2)。

那么显然, 把0变成1, 而问号变成T串上该位置的数字

那么额外的操作数就是0变成1, 也就是配对完多余的数目, 也就是ans1 - ans2

所以总操作数 = 配对消耗的操作+问号变化的操作 + 0变成1的操作数

=min(ans1, ans2) + ans1 - ans2 + que

= ans2 + ans1 - ans2 + que

= ans1 + que

这里的ans1是ans1和ans2中的最大值。

所以符合开头讲的式子

(3)如果匹配完多余的是同一位置上S串为1T串为0(ans1 < ans2)。

那么这个时候就只有替换一种可能了(因为只能0变成1不能1变成0)

那么替换哪里的呢, 前面替换好了不动, 那么就替换问号, 问号中

同一位置是1的, 把问号变成0, 然后0和上面说的1替换, 就匹配成功了

所以这个时候的操作数就是多余的个数, 也就是(ans2 - ans1)。

所以总操作数 = ans1 + ans2 - ans1 + que = ans2 +que

ans2依然是ans1和ans2中的最大值, 同理就可以得出开头那个式子。

呼~终于写完了, 真的是大道至简, 推到最后的式子非常的简单。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std; const int MAXN = 112;
char s[MAXN], t[MAXN]; int main()
{
int T, kase = 0;
scanf("%d", &T); while(T--)
{
int s1 = 0, t1 = 0, ans1 = 0, ans2 = 0, que = 0;
scanf("%s%s", s, t); REP(i, 0, strlen(s))
{
if(s[i] == '1') s1++;
if(t[i] == '1') t1++;
if(s[i] == '?') que++;
if(s[i] != t[i] && s[i] == '1') ans1++;
if(s[i] != t[i] && s[i] == '0') ans2++;
} if(s1 > t1) printf("Case %d: -1\n", ++kase);
else printf("Case %d: %d\n", ++kase, que + max(ans1, ans2));
} return 0;
}

紫书 习题8-3 UVa 12545 (构造法)的更多相关文章

  1. 紫书 习题8-7 UVa 11925(构造法, 不需逆向)

    这道题的意思紫书上是错误的-- 难怪一开始我非常奇怪为什么第二个样例输出的是2, 按照紫书上的意思应该是22 然后就不管了,先写, 然后就WA了. 然后看了https://blog.csdn.net/ ...

  2. 紫书 习题 8-24 UVa 10366 (构造法)

    又是一道非常复杂的构造法-- #include<cstdio> #include<algorithm> #define REP(i, a, b) for(int i = (a) ...

  3. 紫书 习题 11-8 UVa 1663 (最大流求二分图最大基数匹配)

    很奇怪, 看到网上用的都是匈牙利算法求最大基数匹配 紫书上压根没讲这个算法, 而是用最大流求的. 难道是因为第一个人用匈牙利算法然后其他所有的博客都是看这个博客的吗? 很有可能-- 回归正题. 题目中 ...

  4. 紫书 习题 11-9 UVa 12549 (二分图最小点覆盖)

    用到了二分图的一些性质, 最大匹配数=最小点覆盖 貌似在白书上有讲 还不是很懂, 自己看着别人的博客用网络流写了一遍 反正以后学白书应该会系统学二分图的,紫书上没讲深. 目前就这样吧. #includ ...

  5. 紫书 习题 8-21 UVa 1621 (问题分析方法)

    知道是构造法但是想了挺久没有什么思路. 然后去找博客竟然只有一篇!!https://blog.csdn.net/no_name233/article/details/51909300 然后博客里面又说 ...

  6. 紫书 习题8-12 UVa 1153(贪心)

    本来以为这道题是考不相交区间, 结果还专门复习了一遍前面写的, 然后发现这道题的区间是不是 固定的, 是在一个范围内"滑动的", 只要右端点不超过截止时间就ok. 然后我就先考虑有 ...

  7. 紫书 习题 11-17 UVa 1670 (图论构造)

    一开始要符合题目条件, 那么肯定没有任何一个点是孤立的, 也就是说没有点的度数是1 所以我就想让度数是1的叶子节点相互连起来.然后WA 然后看这哥们的博客 https://blog.csdn.net/ ...

  8. 紫书 习题 8-22 UVa 1622 (构造法)

    这道题的构造法真的复杂--要推一堆公式--这道题写了几天了--还是没写出来-- 一开始简单的觉得先左右来回, 然后上下来回, 然后把剩下的执行完了好了, 然后就WA. 然后换了个思路, 觉得是贪心, ...

  9. 紫书 习题 11-15 UVa 1668 (图论构造法)

    参考了http://www.bubuko.com/infodetail-1276416.html 首先是逆向思维, 向把每条边看作一条路径, 然后再去合并 然后我们讨论怎么样合并时最优的 我们讨论当前 ...

随机推荐

  1. Codeforces Round #506 (Div. 3) A-C

    CF比赛题解(简单题) 简单题是指自己在比赛期间做出来了 A. Many Equal Substrings 题意 给个字符串t,构造一个字符串s,使得s中t出现k次;s的长度最短 如t="c ...

  2. css鼠标滑过出现文字效果

    模仿淘宝上鼠标移动到商品图片时,出现的文字效果. 1.效果图                                鼠标移动到粉红色的区域,则出现黄色部分. 2.代码 <!DOCTYPE ...

  3. 算法21----重塑矩阵 LeetCode566

    1.题目 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据. 给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重 ...

  4. tcpsock.v2 与 ecocache

    因为很不满意 tcpsock 的设计与实现,及有意专为譬如游戏服务器端开发设计一套 TCP 网络库,所以年初即有了 tcpsock.v2 的开发计划,于是粗略整理出了以下几条目标计划: 1) TcpC ...

  5. C语言基本语法——数组

    一.一维数组 1.什么是数组 2.数组语法 3.下标 4.初始化 5.数组名和数组首地址 二.一维数组的应用 1.数组的赋值与拷贝 2.数组的正反遍历 3.随机数 4.数组乱序 5.数组的重复 三.二 ...

  6. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)

    题目大意:略 由于字符集大,要用map维护Trie树 并不能用AC自动机的Trie图优化,不然内存会炸 所以我用AC自动机暴跳fail水过的 显然根据喵星人建AC自动机是不行的,所以要根据问题建 然而 ...

  7. [读书笔记] Python 数据分析 (十一)经济和金融数据应用

    resample: 重采样函数,可以按照时间来提高或者降低采样频率,fill_method可以使用不同的填充方式. pandas.data_range 的freq参数枚举: Alias Descrip ...

  8. nginx1.15.8源码安装

    useradd www -s /sbin/nologin -M yum -y install gcc  pcre-devel openssl-devel cd /usr/local/src wget ...

  9. spring security中当前用户信息

    1:如果在jsp页面中获取可以使用spring security的标签库 在页面中引入标签   1 <%@ taglib prefix="sec" uri="htt ...

  10. java中的hachcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...