题意:一个m行n列的图由#、*、o三种符号组成,分别代表冰山、海域、浮冰,问最多可放的炮舰数(要求满足以下条件)

1、炮舰只可放在海域处

2、两个炮舰不能放在同一行或同一列(除非中间隔着一个或多个冰山)

分析:

1、如果单纯只考虑不能放在同一行同一列,那就是行号与列号的匹配,原理与UVALive 6811 Irrigation Line(二分图最小点覆盖--匈牙利算法)相同。

2、但现在隔着冰山可以放置炮舰,那假设某一行被冰山分隔成两部分,这一行的前半部分和后半部分可以看做是两行,再应用“行号”与“列号”的匹配的原理

3、既然要行号与列号匹配,那就要分别按照行和列给图标号

举例如下:

(1)若按行,则将海域从1开始标号,如果是连续的海域那标号相同,若有冰山分隔,标号加1.

PS:例如第三行22#3,此处2是形式意义上的第二行,因为有上述放置炮舰的原则,可以理解为是可以放置炮舰的第2行,而由于有冰山分隔,所以这一行的前后互不干扰,因此3可以理解为是可以放置炮舰的第3行

(2)按列同理

4、理论上讲海域可以放置炮舰,也就是说,有标号的地方可以放置炮舰,每一个放置的地方都是一个行号与列号的匹配,由此可得如下匹配

5、一条连线代表一个可放置的炮舰,求最大匹配即可

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) a < b ? a : b
#define Max(a, b) a < b ? b : a
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1};
const int dc[] = {-1, 1, 0, 0};
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MAXN = 50 + 10;
const int MAXT = 2500 + 10;
using namespace std;
char a[MAXN][MAXN];
int x[MAXN][MAXN];
int y[MAXN][MAXN];
int mp[MAXT][MAXT];
bool used[MAXT];
int match[MAXT];
int m, n, cnt1, cnt2;
void deal_row(){cnt1 = 1;for(int i = 0; i < m; ++i){bool flag = false;for(int j = 0; j < n; ++j){if(a[i][j] == '*'){x[i][j] = cnt1;flag = true;}if(a[i][j] == '#'){++cnt1;flag = false;}}if(flag) ++cnt1;}
}
void deal_column(){cnt2 = 1;for(int i = 0; i < n; ++i){bool flag = false;for(int j = 0; j < m; ++j){if(a[j][i] == '*'){y[j][i] = cnt2;flag = true;}if(a[j][i] == '#'){++cnt2;flag = false;}}if(flag) ++cnt2;}
}
bool Find(int x){for(int i = 1; i < cnt2; ++i){if(mp[x][i] && !used[i]){used[i] = true;if(!match[i] || Find(match[i])){match[i] = x;return true;}}}return false;
}
void solve(){int cnt = 0;for(int i = 1; i < cnt1; ++i){memset(used, false, sizeof used);if(Find(i)) ++cnt;}printf("%d\n", cnt);
}
int main(){int T;scanf("%d", &T);while(T--){memset(a, 0, sizeof a);memset(x, 0, sizeof x);memset(y, 0, sizeof y);memset(mp, 0, sizeof mp);memset(match, 0, sizeof match);scanf("%d%d", &m, &n);for(int i = 0; i < m; ++i)scanf("%s", a[i]);deal_row();deal_column();for(int i = 0; i < m; ++i){for(int j = 0; j < n; ++j){if(a[i][j] == '*'){mp[x[i][j]][y[i][j]] = 1;}}}solve();}return 0;
}

转载于:https://www.cnblogs.com/tyty-Somnuspoppy/p/6036855.html

HDU 5093 Battle ships(二分图最大匹配)相关推荐

  1. HDU 1281 棋盘游戏 【二分图最大匹配】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1281 题意概括: 有N*M大的棋盘,要在里面放尽量多的"车",求最多能放的车的个数, ...

  2. 解题报告 (九) 二分图最大匹配

    文章目录 二分图最大匹配 解题报告 一.最大匹配模板题 HDU 1083 Courses HDU 2063 过山车 HDU 1528 Card Game Cheater HDU 1179 Olliva ...

  3. HDU 3729 I'm Telling the Truth(二分图最大匹配)

    HDU 3729 I'm Telling the Truth(二分图最大匹配) http://acm.hdu.edu.cn/showproblem.php?pid=3729 题意: 一位老师想问N位同 ...

  4. HDU - 1054 Strategic Game(最小点覆盖-二分图最大匹配)

    题目链接:点击查看 题目大意:给出一棵树,现在要在节点上放置士兵,每个士兵可以监视与其所在的节点直接相连的节点,问最少需要多少个士兵才能将整棵树都监视到 题目分析:求最少的节点,以保证每条边都有一个端 ...

  5. HDU - 2389 Rain on your Parade(Hopcroft-Krap算法求二分图最大匹配)

    题目链接:点击查看 题目大意:给出n个人和m个雨伞,t分钟后就要下雨了,现在给出每个人的坐标和速度,以及雨伞所在的坐标,每个雨伞只能容纳一个人,题目问最多有多少个人能不被淋到 题目分析:二分图最大匹配 ...

  6. HDU - 1528 Card Game Cheater(二分图最大匹配)

    题目链接:点击查看 题目大意:题意有点像求田忌赛马的最优解,大概意思就是现在有两个人,每个人都有n张不同的扑克牌,扑克牌的大小首先以点数来确定,点数相同的情况下以花色来决定,红桃(Heart)> ...

  7. HDU - 1150 Machine Schedule(最小点覆盖-二分图最大匹配)

    题目链接:点击查看 题目大意:现在有一个机器A和一个机器B,A机器有n种模式,B机器有m种模式,现在有k次工作需要完成,每次工作的信息为: id x y:编号为id,在A机器要用x模式完成,在B机器要 ...

  8. HDU - 5090 Game with Pearls(二分图最大匹配)

    题目链接:点击查看 题目大意:杰瑞和汤姆在玩游戏,游戏规则是:汤姆会拿来N个容器,每个容器内一开始就会包含1~N个小球,现在轮到杰瑞操作了,杰瑞可以选择往每个容器里加入0个或者任意k的倍数个小球,问杰 ...

  9. HDU - 2063 过山车(二分图最大匹配)

    题目链接:点击查看 题目大意:中文题目,不多赘述 题目分析:二分图最大匹配问题,匈牙利经典算法模板题,感觉这个博客写的很好,插个眼: https://article.itxueyuan.com/Aea ...

最新文章

  1. SVN如何将版本库url访问地址中的https改为http
  2. Java基于自定义注解的面向切面的实现
  3. 浅谈Linux中ldconfig和ldd的用法
  4. python如何输出百分比的数字_Python如何输出百分比
  5. Android自定义组合控件--EditText和Button组合成带有清空EditText内容功能的复合控件
  6. 信用卡多还钱了怎么办?
  7. 三维旋转四元数系列(3.四元数定义与基本性质)
  8. Java中含有泛型的 JSON 反序列化问题
  9. Android开发笔记(一百三十一)水波图形与水波动画
  10. 小米pro笔记本2017款BIOS降级0603
  11. Visual Studio 2022安装时Visual Studio Installer稍等片刻...正在提取文件 进度条不动 0B每秒-已解决
  12. 计算机组成原理补码减法,补码加减法运算(计算机组成原理).ppt
  13. apache mediawiki 安装_mediawiki安装使用
  14. 0x0000007b电脑蓝屏的解决方法
  15. 力扣---LeetCode20. 有效的括号(栈)
  16. 《论语》原文及其全文翻译 学而篇1
  17. 淘宝放大镜插件(vue-piczoom)
  18. Java取数的整数及小数部分
  19. 致远OA wpsAssistServlet 任意文件上传漏洞 漏洞复现
  20. linux实验实训报告,linux实验实训报告.doc

热门文章

  1. Struts2 之配置文件编写,动作类(01)
  2. 美通社祝各位端午安康!
  3. MyBatisPlus学习笔记【part2】
  4. NFT 2.0:创新潜力与投资指南
  5. 老电脑玩游戏又卡又慢,怎么办?
  6. 天明创新受邀出席华为全联接大会,通过AI科技实现尘肺病的预防性筛查
  7. 企业员工情绪分析,帮助你解决员工情绪问题
  8. 讲述我一段自己打游戏的感受
  9. C# 打开文件夹FolderBrowserDialog与打开文件OpenFileDialog浅析
  10. 详解git pull命令和使用过程中遇到的常见问题:fatal: ‘origin‘ does not appear to be a git repository