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. iOS越狱后必装软件

    iOS越狱后就跟ubuntu没两样了,很多ubuntu下常用的软件都要装一下 openssh 这个软件可以让我们能够登录iphone Apt-get 用这个软件可以安装很多软件,主要是一些工具调试类软 ...

  2. 《Python魔法大冒险》003 两个神奇的魔法工具

    魔法师:小鱼,要开始编写魔法般的Python程序,我们首先需要两个神奇的工具:Python解释器和代码编辑器. 小鱼:这两个工具是做什么的? 魔法师:你可以把Python解释器看作是一个魔法棒,只要你 ...

  3. 【项目源码】基于JSP动漫论坛的设计与实现

    动漫论坛项目主要用于实现动漫爱好者的互相交流,基本功能包括:注册用户.登录.浏览帖子.发布新帖.回复帖子.等.本系统结构如下: (1)普通用户: 注册用户:如果用户为非会员用户,通过注册,经审核通过之 ...

  4. Spring Bean 的作用域(Bean Scope)

    前言 大家好,我是 god23bin,今天我们来聊一聊 Spring 框架中的 Bean 作用域(Scope). 什么是 Bean 的作用域? 我们在以 XML 作为配置元数据的情况下,进行 Bean ...

  5. RabbitMQ入门实践

    一.概述: 大多应用中,可通过消息服务中间件来提升系统异步通信.扩展解耦能力. 1.消息服务中两个重要概念: 消息代理(message broker)和目的地(destination)当消息发送者发送 ...

  6. PLC通过Modbus转Profinet网关与合康变频器Modbus通讯案例

    PLC通过Modbus转Profinet网关(XD-MDPN100)与合康变频器Modbus通讯,实现了两个设备之间的数据交互.Profinet是一种基于以太网的实时工控网络协议,而Modbus是一种 ...

  7. Jellyfin Documentation

    Skip to main content     Introduction On this page Welcome to the Jellyfin Documentation Jellyfin is ...

  8. Rust WebAssembly 绑定输入类型(基于 Serde)

    前言 单位有个项目要共享前后端检查策略后端用的正好也是 Rust,但是 Rust 默认的 wasm-bindgen 包中提供的转换操作非常少,像 Vec<T> <=> Arra ...

  9. junit4单元测试报错Invalid project specified

    junit4单元测试报错Invalid project specified. 前天在进行单元测试的时候出现了Invalid project specified的报错查了一下发现是项目名字的问题.项目名 ...

  10. 最新 2023.2 版本 IDEA 永久破解教程,IDEA 破解补丁永久激活(亲测有效)

    最近 jetbrains 官方发布了 2023.2 版本的 IDEA,之前的激活方法并不支持这个新的版本. 下面是最新的激活教程,激活步骤和之前是类似的,只是换用了不同的补丁文件. 本教程支持 Jet ...