当前位置:网站首页>【ACWing】406. 放置机器人
【ACWing】406. 放置机器人
2022-08-01 23:47:00 【记录算法题解】
题目地址:
https://www.acwing.com/problem/content/description/408/
给出一个地图(网格),格子分为空地,草地,墙壁。要在空地上放能向上下左右 4 4 4个方向发射激光的机器人。墙壁能挡住激光,草地不能挡住激光也不能放机器人。在机器人不能互相打到对方的情况下,最多放置多少个机器人。
输入格式:
第一行包含整数 T T T,表示共有 T T T组测试数据。
每组数据第一行包含两个整数 m m m和 n n n,表示地图的大小为 m m m行 n n n列。
接下来 m m m行,每行包含 n n n个字符,用来描述整个地图。#
代表墙壁,*
代表草地,o
代表空地。
输出格式:
每组测试数据在第一行输出Case :id
,id
是数据编号,从 1 1 1开始。
第二行包含一个整数,表示机器人的个数。
数据范围:
1 ≤ m , n ≤ 50 1≤m,n≤50 1≤m,n≤50
思路是二分图。将除了墙的地面定义一个等价关系叫行连通,两个非墙地面行连通当且仅当从一个能沿着行不经过墙走到另一个。那么这个等价关系可以将所有的非墙地面分为若干个等价类,我们把这些等价类编号为 1 , 2 , . . . , r 1,2,...,r 1,2,...,r;同理将列连通等价类编号为 1 , 2 , . . . , c 1,2,...,c 1,2,...,c。将 1 , 2 , . . . , r 1,2,...,r 1,2,...,r视为二分图左边的点, 1 , 2 , . . . , c 1,2,...,c 1,2,...,c视为二分图右边的点,如果某个行连通块和某个列连通块有交集,并且交集是o
即空地,则将他们的编号之间连一条边。首先,这个二分图的任何一个匹配对应着一种放置方案:每条边对应一个空地,并且同一个行连通块里只能有一个机器人(因为会互相攻击),同一个列连通块也只能有一个机器人。其次,任意一个放置方案,对应一个匹配。所以最多的机器人放置方案一定就是二分图的最大匹配,从而可以用匈牙利算法来做。代码如下:
#include <cstring>
#include <iostream>
using namespace std;
const int N = 55, M = 2550;
int n, m, rcnt, ccnt;
char a[N][N];
int rid[N][N], cid[N][N];
int match[M];
bool vis[M];
int h[M], e[M], ne[M], idx;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
bool dfs(int u) {
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (vis[v]) continue;
vis[v] = true;
if (!match[v] || dfs(match[v])) {
match[v] = u;
return true;
}
}
return false;
}
int main() {
int T;
scanf("%d", &T);
for (int t = 1; t <= T; t++) {
memset(h, -1, sizeof h);
idx = 0;
memset(rid, 0, sizeof rid);
memset(cid, 0, sizeof cid);
scanf("%d%d", &m, &n);
for (int i = 1; i <= m; i++) scanf("%s", a[i] + 1);
rcnt = 1, ccnt = 1;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) {
if (a[i][j] != '#') {
while (j <= n && a[i][j] != '#') rid[i][j++] = rcnt;
rcnt++;
}
}
for (int j = 1; j <= n; j++)
for (int i = 1; i <= m; i++) {
if (a[i][j] != '#') {
while (i <= m && a[i][j] != '#') cid[i++][j] = ccnt;
ccnt++;
}
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (a[i][j] == 'o') add(rid[i][j], cid[i][j]);
int res = 0;
memset(match, 0, sizeof match);
// 行连通块的个数为rcnt - 1
for (int i = 1; i < rcnt; ++i) {
memset(vis, 0, sizeof vis);
if (dfs(i)) res++;
}
printf("Case :%d\n%d\n", t, res);
}
}
每组数据时间复杂度 O ( ( m n ) 2 ) O((mn)^2) O((mn)2),空间 O ( m n ) O(mn) O(mn)。
边栏推荐
- 几道关于golang并发的面试题
- CDH6的Hue打开出现‘ascii‘ codec can‘t encode characters
- 如何更好的理解的和做好工作?
- 根本上解决mysql启动失败问题Job for mysqld.service failed because the control process exited with error code
- LocalDateTime转为Date类型
- 在CDH的hue上的oozie出现,提交 Coordinator My Schedule 时出错
- 分享一份接口测试项目(非常值得练手)
- 2022 6th Strong Net Cup Part WP
- 如何用Redis实现分布式锁?
- [Camp Experience Post] 2022 Cybersecurity Summer Camp
猜你喜欢
Flink Yarn Per Job - Yarn应用
2022第六届强网杯部分wp
Dynamic Scene Deblurring with Parameter Selective Sharing and Nested Skip Connections
sys_kill system call
Chrome书签插件,让你实现高效整理
在MySQL中使用MD5加密【入门体验】
UML diagram of soft skills
Share an interface test project (very worth practicing)
chrome copies the base64 data of an image
Building a cloud-native DevOps environment
随机推荐
problem solved
Docker实践经验:Docker 上部署 mysql8 主从复制
分享一份接口测试项目(非常值得练手)
PostgreSQL Basics--Common Commands
Avoid , ,
, and tagsChapter 11 Working with Dates and Times
npm npm
20220725 Information update
很多人喜欢用多御安全浏览器,竟是因为这些原因
numpy.around
Chapter 12 End-User Task As Shell Scripts
CDH6 Hue to open a "ASCII" codec can 't encode characters
【MySQL系列】MySQL索引事务
Calculate the angle of a line defined by two points
Artifact XXXwar exploded Artifact is being deployed, please wait...(已解决)
架构基本概念和架构本质
高效工作文档产出归类
color transparency parameter
Flink Yarn Per Job - CliFrontend
YOLO等目标检测模型的非极大值抑制NMS和评价指标(Acc, Precision, Recall, AP, mAP, RoI)、YOLOv5中[email protected]与