4554: [Tjoi2016&Heoi2016]游戏

Description

在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看
是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张
地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一
列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张n*m的网格地图:其中*代表空地,炸弹的威力可
以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸
弹的威力是不能穿透的,不能在此放置炸弹。例如:给出1*4的网格地图*xx*,这个地图上最多只能放置一个炸弹
。给出另一个1*4的网格地图*x#*,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最
多能放置多少炸弹

Input

第一行输入两个正整数n,m,n表示地图的行数,m表示地图的列数。1≤n,m≤50。接下来输入n行m列个字符,代表网
格地图。*的个数不超过n*m个

Output

输出一个整数a,表示最多能放置炸弹的个数

Sample Input

4 4
#∗∗∗
∗#∗∗
∗∗#∗
xxx#

Sample Output

5
 
最近在学二分图匹配,随便找了一道发现完全没有思路……没有看出来是二分图匹配……
思维不够活跃还没有形成套路啊
正式讲一下做法……
每个点看成一条边,拆点,将每个点分别拆成以行,列为标准的两点,遇到#视为换行/列,
再缩点,在一个连通块的点缩为一点。
令以行为标准的点为左边的点,以列为标准的点为右边的点。
(因为对于地图上的点,一个连通块中只能有一个点放炸弹,以此连接行列,
对应二分图中一个点只能有一个匹配,所以可以把这个看做二分图。)
接着匹配即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define Max 205
int n,m,num1=1,num2=1,dis=Max,res=0;
char s[100][100];
int x[3000][1300],y[3000][3000],mp[3000][3000],dx[10000],dy[10000],cx[10000],cy[10000],vis[10000],pdx[10000],pdy[10000];
int bfs()
{
memset(dx,0,sizeof(dx));
memset(dy,0,sizeof(dy));
dis=Max;
queue<int> q;
for (int i=1;i<=num1;i++)
{
if (!cx[i]&&pdx[i])
q.push(i);
}
while (!q.empty())
{
int u=q.front();
q.pop();
if (dx[u]>dis) break;
for (int i=1;i<=num2;i++)
{
if (mp[u][i]&&!dy[i]&&pdy[i])
{
dy[i]=dx[u]+1;
if (!cy[i]) dis=dy[i];
else
{
dx[cy[i]]=dy[i]+1;
q.push(cy[i]);
}
}
}
}
return dis!=Max;
}
int find(int u)
{
for (int i=1;i<=num2;i++)
{
if (!vis[i]&&mp[u][i]&&dy[i]==dx[u]+1&&pdy[i])
{
vis[i]=1;
if (cy[i]&&dy[i]==dis) continue;
if (!cy[i]||find(cy[i]))
{
cx[u]=i;cy[i]=u;
return 1;
}
}
}
return 0;
} int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%s",s[i]+1);//输入
for (int i=1;i<=n;i++)//以行为标准
{
for (int j=1;j<=m;j++)
{
if (s[i][j]=='#') num1++;//每个num1相同的点即可缩为一个点
x[i][j]=num1;
pdx[num1]=1;
}
num1++;
}
for (int j=1;j<=m;j++)//以列为标准
{
for (int i=1;i<=n;i++)
{
if (s[i][j]=='#') num2++;//同上
y[i][j]=num2;
pdy[num2]=1;
}
num2++;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
if(s[i][j]=='*')//连边
{
mp[x[i][j]][y[i][j]]=1;
//mp[y[i][j]][x[i][j]]=1;
}
}
while (bfs())//二分图匹配,这里用的hopcroft-karp算法,主要想练一下……
{
memset(vis,0,sizeof(vis));
for (int i=1;i<=num1;i++)
{
if (!cx[i]&&pdx[i])
res+=find(i);
}
} cout<<res;
return 0;
}

bzoj4554: [Tjoi2016&Heoi2016]游戏 二分图匹配的更多相关文章

  1. BZOJ 4554: [Tjoi2016&Heoi2016]游戏 二分图匹配

    4554: [Tjoi2016&Heoi2016]游戏 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4554 Descripti ...

  2. 4554: [Tjoi2016&Heoi2016]游戏 二分图匹配

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4554 题解: 如果没有硬石头的话,就是’*‘点对应的行列建边,然后跑最大匹配 硬石头什么 ...

  3. bzoj4554: [Tjoi2016&Heoi2016]游戏(二分图匹配)

    4554: [Tjoi2016&Heoi2016]游戏 题目:传送门 题解: 一道很牛逼的匈牙利..和之前模拟赛的一道题有点相似(不过这题不用完美匹配) 我们可以把连续的行和列全部编号(如果之 ...

  4. 【BZOJ4554】[Tjoi2016&Heoi2016]游戏 二分图最大匹配

    [BZOJ4554][Tjoi2016&Heoi2016]游戏 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个炸弹,看 ...

  5. BZOJ4554 - [TJOI2016&HEOI2016]游戏

    原题链接 Description 给出一个的地图,地图上有空地.软石头和硬石头.求在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到.炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威 ...

  6. [BZOJ4554][TJOI2016&&HEOI2016]游戏(匈牙利)

    4554: [Tjoi2016&Heoi2016]游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 857  Solved: 506[Sub ...

  7. BZOJ4554: [Tjoi2016&Heoi2016]游戏

    Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个炸弹,看 是否能炸到对手,或者躲开对手的炸弹.在玩游戏的过程中,小H想到了这样一 ...

  8. BZOJ 4554 [Tjoi2016&Heoi2016]游戏 ——二分图

    出原题,直接二分图匹配即可. #include <cstdio> #include <vector> #include <cstring> using namesp ...

  9. BZOJ4554: [Tjoi2016&Heoi2016]游戏 luoguP2825 loj2057

    题面描述:尽可能多的放置符合要求的炸弹. 分析: 在i,j处放置炸弹,则在第i行,上一个硬石头之后,下一个硬石头之前,第j列,上一个硬石头之后,下一个硬石头之前,不能再次放置炸弹. 首先,这个题,一看 ...

随机推荐

  1. stm32 Bootloader设计(YModem协议) (转)

    源:stm32 Bootloader设计(YModem协议) 相信很多人都希望,不开盖就可以对固件进行升级吧,就像手机那些.下文中的bootload就来实现这样的功能. 前段时间有项目关于Bootlo ...

  2. UVA 10689 Yet another Number Sequence

    简单矩阵快速幂. if(m==1) MOD=10; if(m==2) MOD=100; if(m==3) MOD=1000; if(m==4) MOD=10000; 剩下的就是矩阵快速幂求斐波那契数列 ...

  3. Leetcode 182. Duplicate Emails

    Write a SQL query to find all duplicate emails in a table named Person. +----+---------+ | Id | Emai ...

  4. lua 函数

    1.函数只有一个参数,且该参数为table 或 字符串时,调用函数可以省略() print"hello world" 同 print("hello world" ...

  5. C# Expression表达式笔记

    整理了一下表达式树的一些东西,入门足够了 先从ConstantExpression 开始一步一步的来吧  它表示具有常量值的表达式 我们选建一个控制台应用程序 ConstantExpression _ ...

  6. IOS开发-UI学习-UINavigationController(导航控制器)的使用

    UINavigationController是IOS 中常用的功能,基本用法如下: 1.在AppDelegate.m中添加如下代码: #import "AppDelegate.h" ...

  7. object 类 toString() 和 equals() 的覆写

    基本作用: objiect类是所有类的父类. 任何一个类定义的时候如果没有明确定义了父类的话,默认父类是Object类. class A extends Object{} 在整个java里面,类的继承 ...

  8. UVa 757 - Gone Fishing

    题目大意:John有h的时间可以去钓鱼,有n湖可钓鱼,以5分钟为时间单位,每个湖初始每个单位时间可钓f条鱼,每下一个时间单位数量减少d条.同时,John只能从1号湖往后走进行钓鱼,湖之间的距离需要t个 ...

  9. centos5.5get 递归下载整个网站

    这个命令可以以递归的方式下载整站,并可以将下载的页面中的链接转换为本地链接. wget加上参数之后,即可成为相当强大的下载工具. wget -r -p -np -k http://xxx.com/xx ...

  10. Grunt之watch详解

    Grunt 之 watch 和 livereload 现在 watch 中已经集成了 livereload ,所以把它们放在一起说明. watch 可以监控特定的文件,在添加文件.修改文件.或者删除文 ...