题意

有一个 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. C++入门经典-例8.1-类的继承

    1:继承是面向对象的主要特征(此外还有封装和多态)之一,它使得一个类可以从现有类中派生,而不必重新定义一个新类.继承的实质就是用已有的数据类型创建新的数据类型,并保留已有数据类型的特点,以旧类为基础创 ...

  2. OkHttp3 拦截器源码分析

    OkHttp 拦截器流程源码分析 在这篇博客 OkHttp3 拦截器(Interceptor) ,我们已经介绍了拦截器的作用,拦截器是 OkHttp 提供的对 Http 请求和响应进行统一处理的强大机 ...

  3. Java - 自动装箱与拆箱详解

    1.装箱与拆箱 装箱,将基本数据类型转为包装类型.拆箱,将包装类型转为基本数据类型. // Byte, Short, Integer, Long, Double, Float, Boolean, Ch ...

  4. Java工具类-HttpUtil

    package com.sh.util; import java.io.IOException; import java.io.UnsupportedEncodingException; import ...

  5. linux升级安装openssh时出现依赖冲突

    通过如下方式下载到openssh安装包 https://www.cnblogs.com/qq931399960/p/11120429.html -rwxrwxrwx. root root Jul : ...

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

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

  7. PMML辅助机器学习算法上线

    在机器学习用于产品的时候,我们经常会遇到跨平台的问题.比如我们用Python基于一系列的机器学习库训练了一个模型,但是有时候其他的产品和项目想把这个模型集成进去,但是这些产品很多只支持某些特定的生产环 ...

  8. 八十一:memcached之telnet操作memcached

    先打开telnet服务否则会报错 确认memcached服务已启动 telnet ip 端口 连上以后敲一下回车 常用的命令: 1.set:在memcached中添加一个key->value,如 ...

  9. Debian系统设置terminal快捷键

    我安装的是debian gnome桌面版.安装完成之后,没有快捷键可以方便的打开terminal,需要自己设置这个快捷键 方法是: 桌面上点击右键==>设置==>键盘 ==>快捷键= ...

  10. mac 安装photoshop + 破解

    项目开发中毫无疑问会用到图片,一般情况都是UI将图片切好的,只是,有时候项目中少了一张图片或者是改变图片的尺寸之类的问题,这里我们就不需要每次都找UI要图片了,作为程序员这些基础工具的使用,咱们还是要 ...