Problem Statement

There is a grid with $H$ rows from top to bottom and $W$ columns from left to right. Let $(i, j)$ denote the square at the $i$-th row from the top and $j$-th column from the left.

Square $(i, j)$ is occupied by an obstacle if $S_{i,j}=$ #, and is empty if $S_{i,j}=$ ..

Takahashi will install some surveillance cameras in the grid.

A surveillance camera can be placed at a square without an obstacle, in one of the four directions: up, down, left, or right.

Multiple surveillance cameras may be placed at the same square.

Each surveillance camera monitors the square it is placed at, and the squares in the direction it is placed in, as far as there is no obstacle in between.

At least how many surveillance cameras are needed to monitor all squares without an obstacle?

Constraints

  • $1 \leq H,W \leq 300$
  • $S_{i,j}$ is . or #.

Input

The input is given from Standard Input in the following format:

$H$ $W$
$S_{1,1}\ldots S_{1,W}$
$\vdots$
$S_{H,1}\ldots S_{H,W}$

Output

Print the answer.


Sample Input 1

3 3
...
.#.
...

Sample Output 1

4

For example, if we install two surveillance cameras at square $(1, 1)$ facing right and down, and another two at square $(3, 3)$ facing up and left, all squares without an obstacle will be monitored.


Sample Input 2

3 5
...##
.#...
...#.

Sample Output 2

5

For example, if we install two surveillance cameras at square $(1, 1)$ facing right and down, another at square $(3, 3)$ facing left, and another two at square $(2, 5)$ facing left and down, all squares without an obstacle will be monitored.

Note that the camera at square $(2, 5)$ facing left cannot monitor square $(2, 1)$, since there is an obstacle in between at square $(2, 2)$.


Sample Input 3

14 107
...........................................................................................................
...........................................................................................................
..#########..###....###########..###.......###...###########..####.......###...###########...###########...
..########..###....###########....###.....###...###########...#####......###..###########...###########....
..#######..###.....###.............###...###....###...........######.....###..###...........###............
..######..###......###..............###.###.....###...........###.###....###..###...........###............
..#####..###.......############......#####......############..###..###...###..###...........############...
..####....###......############.......###.......############..###...###..###..###...........############...
..###......###.....###................###.......###...........###....###.###..###...........###............
..##........###....###................###.......###...........###.....######..###...........###............
..#..........###...############.......###.......############..###......#####..############..############...
..............###...###########.......###........###########..###.......####...###########...###########...
...........................................................................................................
...........................................................................................................

Sample Output 3

91

最优化问题,在尝试了贪心,dp后,走向网络流。

首先一个监控有4个方向,但是只有两个方向有用。因为你在一个地方放置向右的监控,效果一定不差于在这个地方往右遇到的第一个障碍的前面或边界放置一个往左的监控。之后不妨设只有向下和向右的两种方向的监控。

另一个结论是,一个点会放向下的监控,当且仅当他位于上边界或者他上面是障碍,不然他的效果1肯定不如再往上一格去放。向右的监控同理。

最大流很难建图,考虑去求最小割。不妨把一个点拆成两个点,一个代表他是否放置往右的监控,一个代表他是否放置往下的监控。源点连向每一个代表是否放置往右监控的店,每一个代表是否放置往下的监控的点连向汇点,流量均为1。对于一个点,处理出他往上最近的一个可以放置的店,他往左最近的一个可以放置的店。这两个点至少要选一个,所以给这两个点分别代表的点中间连一条流量为正无穷的边。那么此时跑最大流,一条边断了,表示他放置往下/往右的监控。那么此时每个点代表的每条边,他的左右都至少1有一个点选了,也就代表这个点被覆盖了。

发现图是二分图,复杂度 \(O((HW)^{1.5})\)

#include<bits/stdc++.h>
using namespace std;
const int N=305,M=3*N*N+6;
int h,w,e_num(1),hd[M],s,t,l,r,q[M],v[M],k,vhd[M],x[N][N],y[N][N],ans;
struct edge{
int v,nxt,f;
}e[N*N*10];
int get(int x,int y)
{
return x*h+w;
}
void add_edge(int u,int v,int f)
{
// printf("%d %d %d\n",u,v,f);
e[++e_num]=(edge){v,hd[u],f};
hd[u]=e_num;
}
char str[N][N];
int bfs()
{
memset(v,0,sizeof(v));
q[l=r=1]=s,v[s]=1;
memcpy(hd,vhd,sizeof(hd));
while(l<=r)
{
for(int i=hd[q[l]];i;i=e[i].nxt)
{
if(!v[e[i].v]&&e[i].f)
{
// printf("%d %d %d\n",q[l],e[i].v,e[i].f);
v[e[i].v]=v[q[l]]+1;
q[++r]=e[i].v;
}
}
++l;
}
// for(int i=1;i<=t;i++)
// printf("%d ",v[i]);
// putchar('\n');
return v[t];
}
int dfs(int x,int flow)
{
if(x==t)
return flow;
int s=0;
for(int&i=hd[x];i;i=e[i].nxt)
{
if(v[e[i].v]==v[x]+1&&e[i].f)
{
int t=dfs(e[i].v,min(flow,e[i].f));
flow-=t,s+=t;
e[i].f-=t,e[i^1].f+=t;
if(!t)
v[e[i].v]=0;
if(!flow)
break;
}
}
return s;
}
int main()
{
scanf("%d%d",&h,&w) ;
s=2*h*w,t=2*h*w+1;
for(int i=0;i<h;i++)
scanf("%s",str[i]);
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
if(str[i][j]=='#')
continue;
k=i*w+j;
if(!i||str[i-1][j]=='#')
{
x[i][j]=k;
add_edge(s,k,1);
add_edge(k,s,0) ;
}
else
x[i][j]=x[i-1][j];
if(!j||str[i][j-1]=='#')
{
y[i][j]=k;
add_edge(k+h*w,t,1);
add_edge(t,k+h*w,0);
}
else
y[i][j]=y[i][j-1];
add_edge(x[i][j],y[i][j]+h*w,1e9);
add_edge(y[i][j]+h*w,x[i][j],0);
}
}
memcpy(vhd,hd,sizeof(hd));
while(bfs())
while(k=dfs(s,2e9))
ans+=k;
printf("%d",ans);
}

[ABC274G] Security Camera 3的更多相关文章

  1. ABC220H - Security Camera

    考虑折半,将点按照标号是否 \(\le \frac{n}{2}\) 分成两个集合 \(S_1, S_2\). 首先原问题的形式有点奇怪,我们不妨统计没有被覆盖覆盖的边为偶数条的情况. 这样一来问题转化 ...

  2. Unity3D重要知识点

    数据结构和算法很重要!图形学也很重要!大的游戏公司很看重个人基础,综合能力小公司看你实际工作能力,看你的Demo. 1.什么是渲染管道? 是指在显示器上为了显示出图像而经过的一系列必要操作. 渲染管道 ...

  3. Unity3D 面试题汇总

    最先执行的方法是: 1.(激活时的初始化代码)Awake,2.Start.3.Update[FixUpdate.LateUpdate].4.(渲染模块)OnGUI.5.再向后,就是卸载模块(TearD ...

  4. Unity随机随学

    1.什么是渲染管道? 是指在显示器上为了显示出图像而经过的一系列必要操作.渲染管道中的步骤很多,都要将几何物体从一个坐标系中变换到另一个坐标系中去. 主要步骤有: 本地坐标->视图坐标-> ...

  5. 越狱Season 1-Episode 15: By the Skin and the Teeth

    Season 1, Episode 15: By the Skin and the Teeth -Pope: doctor...you can leave. 医生你得离开 -Burrows: It's ...

  6. U3D常用题

    最先执行的方法是:1.(激活时的初始化代码)Awake,2.Start.3.Update[FixUpdate.LateUpdate].4.(渲染模块)OnGUI.5.再向后,就是卸载模块(TearDo ...

  7. Questions about UIUC and USC

    Questions about UIUC and USC I am admitted to University of Illinois at Urbana-Champaign (UIUC) Prof ...

  8. Unity3D 面试ABC

    最先执行的方法是: 1.(激活时的初始化代码)Awake,2.Start.3.Update[FixUpdate.LateUpdate].4.(渲染模块)OnGUI.5.再向后,就是卸载模块(TearD ...

  9. U3D 基础

    千里之行,始于足下! 最先执行的方法是:1.(激活时的初始代码)Awake2.Start3.Update(FixUpdate,LateUpdate)4.渲染模块(OnGUI)5.再向后,就是卸载模块( ...

  10. Unity3d笔试题大全

    1.       [C#语言基础]请简述拆箱和装箱. 答: 装箱操作: 值类型隐式转换为object类型或由此值类型实现的任何接口类型的过程. 1.在堆中开辟内存空间. 2.将值类型的数据复制到堆中. ...

随机推荐

  1. LeetCode952三部曲之二:小幅度优化(137ms -> 122ms,超39% -> 超51%)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<LeetCode952三部曲& ...

  2. Adobe全家桶PS、PR、AU等2022正版永久有效,无需破解直接安装就能用

    [Adobe全家桶]已经亲测绝对好用,下载地址: 关注我的wx公众号"奋斗在IT"回复1013获取下载地址.

  3. Webpack性能优化 SplitChunksPlugin的使用详解

    使用前景 在vue.react等使用webpack为项目打包工具的前端项目,在开发过程中,随着项目功能的逐渐增加,项目整体体积的不断增加,打包的时长和打包后部署的项目体积也在不停的增长,这样可能会导致 ...

  4. 探析ElasticSearch Kibana在测试工作中的实践应用

    一. 为什么使用ES Kibana 离线数据测试中最重要的就是数据验证,一部分需要测试es存储数据的正确性,另一部分就需要验证接口从es取值逻辑的正确性.而为了验证es取值逻辑的正确性,就需要用到Ki ...

  5. FreeSWITCH容器化问题之rtp端口占用

    操作系统 :CentOS 7.6_x64.debian 11 (bullseye,docker) FreeSWITCH版本 :1.10.9 Docker版本:23.0.6 FreeSWITCH容器化带 ...

  6. .NET Core使用SkiaSharp快速生成二维码( 真正跨平台方案)

    前言 在.NET 6之前我们一直是使用QRCoder来生成二维码(QRCoder是一个非常强大的生成二维码的组件,用到了System.Drawing.Common 包),然后从.NET 6开始,当为非 ...

  7. a-2b

    a-2b   描述 输入两个高精度数a和b,求a-2b的值. 输入 输入两行,第一行是被减数a,第二行是减数b(a>2b并且a,2b的位数不同且不存在借位,且b+b不存在进位). 输出 一行,即 ...

  8. Java-全网最详细数据结构

    数构&算法:数据结构 数据结构是计算机存储.组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率.数据结构往 ...

  9. linux 批量替换文件内容

    1.批量查找某个目下文件的包含的内容,例如: #   grep -rn "要找查找的文本" ./ 2.批量查找并替换文件内容. #   sed -i "s/要找查找的文本 ...

  10. VK Cup 2016 - Round 1 (CF639)

    A. Bear and Displayed Friends Div2 的题,不写. B. Bear and Forgotten Tree 3 这种东西怎么评蓝的? Description 给定 \(n ...