题意

有一个 n*n 的图,. 代表空白区域,X 代表墙,现在要在空白区域放置结点,要求同一行同一列只能放一个,除非有墙阻隔,问最多能放多少个点

思路

只有在墙的阻隔情况下,才会出现一行/列出现多个点的情况,那么可以考虑进行缩点,将同一行且没有墙体阻隔的区域缩成一个点,放到左点集中,将同一列且没有墙体阻隔的区域缩成一个点,放到右点集中,从而建成一个二分图

假设 i 为行编号,j 为列编号,若 i-j 之间存在一条边,就相当于在方格 (i,j) 上放了一个点,这个假设使得在没有墙体阻隔的情况下,i 行 j 列不能再放其他的点,那么在不考虑 不能同行同列 的情况下,将所有边连接起来,即行列缩点后,对应方格编号连边

建好图后,在图上求最大匹配即可

C++代码一

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=1E9+;
const int N=+;
const int dx[]={-,,,};
const int dy[]={,,-,};
using namespace std;
int n;//n行n列
bool vis[N];//vis[i]表示是否在交替路中
int link[N];//存储连接点
int G[N][N];//存边
char str[N][N];
int x[N][N],cntX;//行点集
int y[N][N],cntY;//列点集
bool dfs(int x){
for(int y=;y<cntY;y++){//对x的每个邻接点
if(G[x][y]==&&!vis[y]){//不在交替路中
vis[y]=true;//放入交替路
if(link[y]==- || dfs(link[y])){//如果是未匹配点,说明交替路是增广路
link[y]=x;//交换路径
return true;//返回成功
}
}
}
return false;//不存在增广路,返回失败
}
int hungarian(){
int ans=;//记录最大匹配数
memset(link,-,sizeof(link));
for(int i=;i<cntX;i++){//从左侧开始每个结点找一次增广路
memset(vis,false,sizeof(vis));
if(dfs(i))//找到一条增广路,形成一个新匹配
ans++;
}
return ans;
}
int main(){ while(scanf("%d",&n)!=EOF&&n){
memset(x,,sizeof(x));
memset(y,,sizeof(y));
memset(G,false,sizeof(G)); for(int i=;i<n;i++)
scanf("%s",str[i]); //对行缩点
cntX=;
for(int i=;i<n;i++){//第i行
for(int j=;j<n;j++){//第j列
if(str[i][j]=='.')//同一区域
x[i][j]=cntX;
if(str[i][j]=='X')//墙体阻隔
cntX++;
}
cntX++;//下一行
} //对列缩点
cntY=;
for(int j=;j<n;j++){//第j列
for(int i=;i<n;i++){//第i行
if(str[i][j]=='.')//同一区域
y[i][j]=cntY;
if(str[i][j]=='X')//墙体阻隔
cntY++;
}
cntY++;//下一列
} //连边
for(int i=;i<n;i++)
for(int j=;j<n;j++)
if(str[i][j]=='.')
G[x[i][j]][y[i][j]]=true; printf("%d\n",hungarian());
}
return ;
}

C++代码二

#include <bits/stdc++.h>
using namespace std;
int n;
struct node
{
int a = , b = ;
};
node id[][];
char mp[][];
bool link[][];
bool vis[];
int use[];
int hcnt,rcnt; void dfsh(int x,int y){
if(y <= n && mp[x][y] == '.'){
id[x][y].a = hcnt;
dfsh(x,y+);
}
} void dfsr(int x,int y){
if(x <= n && mp[x][y] == '.'){
id[x][y].b = rcnt;
dfsr(x+,y);
}
} int find(int x)
{
for (int s = ; s < rcnt; s++) {
if (link[x][s] && !vis[s]) {
vis[s] = ;
if (use[s] == || find(use[s])) {
use[s] = x;
return ;
}
}
}
return ;
} int main(int argc, char const *argv[])
{
while(cin >> n && n){
for(int i = ;i <= n ;i ++){
cin >> mp[i] + ;
} memset(id,,sizeof id);
memset(link,,sizeof link);
memset(use,,sizeof use);
hcnt = rcnt = ;
for(int i = ;i <= n;i ++){
for(int j = ;j <= n ;j ++){
if(mp[i][j] == 'X'){
continue;
}
if(id[i][j].a == ){
dfsh(i,j);
hcnt ++;
}
if(id[i][j].b == ){
dfsr(i,j);
rcnt ++;
}
link[id[i][j].a][id[i][j].b] = ;
}
}
int sum = ;
for(int i = ;i < hcnt;i ++){
memset(vis,,sizeof vis);
if(find(i)) sum ++;
}
printf("%d\n",sum );
} return ;
}

C++代码三

#define N 6
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char k[N][N];
int book[N][N];
int n,ma;
void dfs(int step)
{
if(step>ma)//保留每次能放得最大碉堡数
{
ma=step;
return;
}
for(int i=; i<n; i++)
{
for(int j=; j<n; j++)
{
if(k[i][j]=='.'&&!book[i][j])//如果这个位置可以放碉堡
{
int a=i,b=i,c=j,d=j;
//向四个方向覆盖,遇到边界或墙停止
while(a>=&&k[a][j]=='.'){book[a][j]++;a--;}
while(b<n&&k[b][j]=='.'){book[b][j]++;b++;}
while(c>=&&k[i][c]=='.'){book[i][c]++;c--;}
while(d<n&&k[i][d]=='.'){book[i][d]++;d++;}
dfs(step+);//放置的碉堡数加1
a=i,b=i,c=j,d=j;
//取消覆盖
while(a>=&&k[a][j]=='.'){book[a][j]--;a--;}
while(b<n&&k[b][j]=='.'){book[b][j]--;b++;}
while(c>=&&k[i][c]=='.'){book[i][c]--;c--;}
while(d<n&&k[i][d]=='.'){book[i][d]--;d++;}
}
}
}
return;
}
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=; i<n; i++)
scanf("%s",k[i]);
memset(book,,sizeof(book));
ma=;
dfs();
printf("%d\n",ma);
}
return ;
}

DFS

Fire Net(HDU-1045)(匈牙利最大匹配)(建图方式)的更多相关文章

  1. Fire Net HDU - 1045 (二分图匹配)

    题意: 给出一张图,图中'X'表示wall,'.'表示空地,可以放置blockhouse同一条直线上只能有一个blockhouse,除非有wall 隔开,问在给出的图中最多能放置多少个blockhou ...

  2. Eliminate the Conflict HDU - 4115(2-sat 建图 hhh)

    题意: 石头剪刀布 分别为1.2.3,有n轮,给出了小A这n轮出什么,然后m行,每行三个数a b k,如果k为0 表示小B必须在第a轮和第b轮的策略一样,如果k为1 表示小B在第a轮和第b轮的策略不一 ...

  3. Meeting HDU - 5521 虚点建图

    Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer John ...

  4. HDU 4292 Food (建图思维 + 最大流)

    (点击此处查看原题) 题目分析 题意:某个餐馆出售f种食物,d种饮料,其中,第i种食物有fi份,第i种饮料有di份:此时有n个人来餐馆吃饭,这n个人必须有一份食物和一份饮料才会留下来吃饭,否则,他将离 ...

  5. 逃生 HDU 4857(反向建图 + 拓扑排序)

    逃生 链接 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必 ...

  6. 神奇的建图方式(Tarjan)——小z玩游戏

    原题来自与:洛谷 P5676(GZOI2017)  链接: https://www.luogu.com.cn/problem/P5676 题面: 题意比较明显,如果已经建好了边,那么跑个Tarjan ...

  7. A - Fire Net - hdu 1045(二分图匹配)

    题意:一个阵地可以向四周扫射,求出来最多能修多少个阵地,墙不可以被扫射透,阵地不能同行或者或者列(有墙隔着例外) 分析:很久以前就做过这道题..当时是练习深搜来着,不过时间复杂度比较高,现在再看突然发 ...

  8. Fire Net HDU - 1045(二分匹配)

    把每一列中相邻的 .  缩为一个点 作为二分图的左边 把每一行中相邻的  .  缩为一个点 作为二分图的右边 然后求最大匹配即可 这题用匈牙利足够了...然而..我用了hk...有点大材小用的感觉// ...

  9. (匹配)Fire Net --hdu --1045

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1045 http://acm.hust.edu.cn/vjudge/contest/view.action ...

随机推荐

  1. vue绑定样式

    使用三目运算符绑定样式 本来以为使用vue模版写法,在绑定单个样式,也就是一个class类名的时候可以直接书写,就像这样 <div id="app"> <div ...

  2. CodeForce 137B

    Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Description " ...

  3. 普通线程类获取service,controller等spring容器类

    package com.zihexin.application.strategy; import org.springframework.beans.BeansException; import or ...

  4. Ubuntu16.04安装nginx(并启用SSL)

    一.安装环境介绍 需要预先安装gcc,通常ubuntu默认自带,所以默认已经有这个环境了,后续步骤默认是使用root账户进行的 二.下载及安装nginx相关组件 1.进入任意目录,我选用的是通常选用的 ...

  5. tp5分页,一看就懂,简单明了(附带额外参数)

    php 代码: $result = $jjModel->where($wheres)->paginate(10,false,['query' => ['peytype'=>$p ...

  6. leetcode-hard-array-454 4sum II-NO

    mycode   过不了...我也不知道为什么... class Solution(object): def fourSumCount(self, A, B, C, D): ""& ...

  7. GLSL语法入门

    变量 GLSL的变量命名方式与C语言类似.变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还有变量名不能以gl_作为前缀,这个是GLSL保留的前缀,用于GLSL的内部变量.当然还有一些 ...

  8. 浏览器端-W3School-HTML:HTML DOM Video 对象

    ylbtech-浏览器端-W3School-HTML:HTML DOM Video 对象 1.返回顶部 1. HTML DOM Video 对象 Video 对象 Video 对象是 HTML5 中的 ...

  9. Oracle 性能之 Enq: CF - contention

    Oracle 性能之 Enq: CF - contention Table of Contents 1. 原因 2. 解决问题 2.1. 针对持有锁进程类型处理 2.1.1. 查看持有锁会话的进程类型 ...

  10. 网络通信框架之volley

    介绍 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行HTTP通信,Htt ...