题意简述

给你一个 01 矩阵,每一次你可以在这个矩阵中找到一个 \(L\) 型,将它全部变成 0。\(L\) 型的定义是在一个 \(2\times2\) 矩阵中,除开一个角之外的图形,其中必须包含至少一个 1。

现在需要你找到将整个矩阵变成 1 的最大操作数。

题目分析

由于 L 型是在一个 2$\times$2 的矩阵中,所以我们不妨从这里开始分析。

1. 如果矩阵没有 0

1 1
1 1

这种情况会有 4 个 1。

显然,第一次操作至少会让三个 1 变成 0,然后转到情况 4,这时候最大操作数是 2

此时,操作数 = 1 的个数 -2。

2. 如果矩阵只有一个 0

0 1
1 1

其中的一种情况是上面这样的,这时候会有 3 个 1。

同样的,第一次操作至少会让两个 1 变成 0,然后转到情况 4,这时候最大的操作数是 2

此时,操作数 = 1 的个数 -1。

3. 如果矩阵只有两个 0

0 1 | 0 0
1 0 | 1 1

其中有两种情况如上图,这时候会有 2 个 1。

这时候第一次操作可以只改变一个 1,接着转到情况 4,最大的操作数是 2

此时,操作数 = 1 的个数。

4. 如果矩阵只有三个 0

0 0
0 1

其中一种情况如上,这时候有 1 个 1.

这时候只能改变一个 1,操作数也就是 1。同时显然,矩阵中没有 1 是操作数是 0,这里便不做分类讨论。

此时,操作数 = 1 的个数。

根据上面的分析,我们可以大胆猜想,设 1 的个数为 x,0 的个数为 y,操作数为 ans,则在 2$\times$2 矩阵中:

\(\begin{cases}
ans &= x-2 &(y=0) \\
ans &= x-1 &(y=1) \\
ans &=x &(y\ge2)
\end{cases}\)

我们尝试将结论推广到普通矩阵中。

没有 0 的情况显然和之前一样。

而这时候就不是只有 1 个 0 的情况,而是在一个 2$\times$2 矩阵中只有 1 个 0。

同样,至少有 2 个 0 的情况也需要转移到在 2$\times$2 矩阵中至少有 2 个 0。

这样我们只要求出 1 的个数并且判断在 2$\times$2 矩阵中有没有至少两个 0 即可。

为什么这种思路是正确的?

一个任意的 n\(\times\)m 矩阵(\(n,m\ge2\)),都会包含若干个 2$\times$2 的矩阵,即使矩阵可能会重叠。

如果其中有一个矩阵有大于 1 个的 0,就可以从这里开始操作,扩展到每个 2$\times$2 矩阵都有大于 1 个的 0,情况简化成最开始分析中的第三种情况。否则就只能按照第二种情况来扩展。

#include<bits/stdc++.h>
using namespace std;
const int N=5e2+5;
int n,m;
int a[N][N]; signed main(){
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
cin>>n>>m;
int suma=0,sumb=0;//suma是0的个数,sumb是1的个数。其实只记录其中的一个也可以
bool f=false;
for(int i=1;i<=n;i++){
string s;
cin>>s;
for(int j=0;j<m;j++) a[i][j+1]=s[j]-'0';
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]==0){
suma++;
//下面判断2*2矩阵中有两个0的情况,注意判断数组越界,用循环也可以
if((i+1<=n&&a[i+1][j]==0)||(i-1>=1&&a[i-1][j]==0)||(j-1>=1&&a[i][j-1]==0)||(j+1<=m&&a[i][j+1]==0)) f=true;//两个0是相邻的
else if((i+1<=n&&j+1<=m&&a[i+1][j+1]==0)||(i-1>=1&&j-1>=1&&a[i-1][j-1]==0)||(i+1<=n&&j-1>=1&&a[i+1][j-1]==0)||(i-1>=1&&j+1<=m&&a[i-1][j+1]==0)) f=true;//两个0称对角
}
else sumb++;
}
}
if(suma==0) cout<<sumb-2<<"\n";//都是1
else if(sumb==0) cout<<"0\n";//都是0
else if(f==false) cout<<sumb-1<<"\n";//所有2*2矩阵中都只有一个0
else cout<<sumb<<"\n";//任意2*2矩阵中有至少两个0
}
return 0;
}

【题解】CF1720C的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. s905l3a系列刷armbian 教你从0搭建自己的博客

    最近服务器又更换了,原来的有一点点小意外(一个电阻给我焊接时搞掉了). 哎~~今天,我淘到了一个好东西----CM311-3a,配置很诱人,价格也不贵,60绰绰有余 比较 CM311-3a N1(炒到 ...

  2. mysql安装及修改密码

    MySQL5.7更改密码时出现ERROR 1054 (42S22): Unknown column 'password' in 'field list' C:\Users\Administrator& ...

  3. Java学习第七周

    这周学习了集合,stream流等知识 List集合 – List系列集合:添加的元素是有序,可重复,有索引 1.ArrayList: 添加的元素是有序,可重复,有索引 2.LinkedList: 添加 ...

  4. SpringCloud之Sentinel

    一. sentinel是什么? 1.概念: 分布式服务架构的流量治理组件. 2.sentinel有什么作用? 2.1 流控:QPS.线程数 2.2 熔断降级:降级-->熔断策略.时长.请求数等 ...

  5. WPF开发快速入门【7】WPF的拖放功能(Drag and Drop)

    概述 本文描述WPF的拖放功能(Drag and Drop). 拖放功能涉及到两个功能,一个就是拖,一个是放.拖放可以发生在两个控件之间,也可以在一个控件自己内部拖放.假设界面上有两个控件,一个Tre ...

  6. springboot配置(yami配置文件,JSR303数据校验,多环境配置)

    yami配置文件 YAML是 "YAML Ain't a Markup Language" (YAML不是一种标记语言)的递归缩写.在开发的这种语言时,YAML 的意思其实是:&q ...

  7. Go 语言入门 1-管道的特性及实现原理

    入坑 go 也快一年了,从今天开始会定期分享一下 Go 语言学习过程中的一些基础知识. go 语言中的管道, 主要是用于协程之间的通信, 比 UNIX 的管道更加轻量和易用. 我们先看一下管道的数据结 ...

  8. 设计模式——桥接模式(Bridge模式)

    基本介绍 桥接模式(Bridge模式):将实现与抽象放在两个不同的类层次中,使两层次可以独立改变 是一种结构型设计模式 说白了就是有多个维度的变化,这样的组合关系如果按照传统的方式会导致类爆炸,所以需 ...

  9. 【Android 逆向】switch 的smail特征

    JAVA 源码 ... String str1 = packedSwitch(1); ... private String packedSwitch(int i) { String str = nul ...

  10. git hooks在业务中的使用

    起因 最近公司项目发生了一起线上事故,最后排查下来是配置文件的问题.项目里application.yml文件内会用@build.time@记录打包时的时间,但是这个写法是build-helper-ma ...