hdu 1045 Fire Net(二分匹配 or 暴搜)
Fire Net
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7998 Accepted Submission(s): 4573Problem DescriptionSuppose
that we have a square city with straight streets. A map of a city is a
square board with n rows and n columns, each representing a street or a
piece of wall.A blockhouse is a small castle that has four
openings through which to shoot. The four openings are facing North,
East, South, and West, respectively. There will be one machine gun
shooting through each opening.Here we assume that a bullet is
so powerful that it can run across any distance and destroy a blockhouse
on its way. On the other hand, a wall is so strongly built that can
stop the bullets.The goal is to place as many blockhouses in a
city as possible so that no two can destroy each other. A configuration
of blockhouses is legal provided that no two blockhouses are on the same
horizontal row or vertical column in a map unless there is at least one
wall separating them. In this problem we will consider small square
cities (at most 4x4) that contain walls through which bullets cannot run
through.The following image shows five pictures of the same
board. The first picture is the empty board, the second and third
pictures show legal configurations, and the fourth and fifth pictures
show illegal configurations. For this board, the maximum number of
blockhouses in a legal configuration is 5; the second picture shows one
way to do it, but there are several other ways.
Your
task is to write a program that, given a description of a map,
calculates the maximum number of blockhouses that can be placed in the
city in a legal configuration.InputThe
input file contains one or more map descriptions, followed by a line
containing the number 0 that signals the end of the file. Each map
description begins with a line containing a positive integer n that is
the size of the city; n will be at most 4. The next n lines each
describe one row of the map, with a '.' indicating an open space and an
uppercase 'X' indicating a wall. There are no spaces in the input file.OutputFor
each test case, output one line containing the maximum number of
blockhouses that can be placed in the city in a legal configuration.Sample Input4.X......XX......2XX.X3.X.X.X.X.3....XX.XX4................0Sample Output5
1
5
2
4Source
渣渣一枚只会暴力搜索,查阅了很多资料以后,也就是找到了一个二分匹配的最简写法。
1.匹配算法(匈牙利算)
题意:给出一个n*n的矩阵,其中‘.’表示空地,‘X’表示城墙,空地上可以放炮台,城墙可以阻挡炮台,任意两个炮台不能照脸。求最多能放多少个炮台。
思路:按照行和列一一对应可以构建一个二分图,最大匹配数就是结果。
比较难想的是怎么建图,对于下图,如果(1,1)和(1,3)这两个点是可以同时放炮台的。这种情况相当于将第一行分成了两行,所以(1,3)应该与 (1,1)区分出来独立建图。开始我的想法是记录该点之前遇到过多少城墙,根据遇到的城墙数+当前行列数+n建图,这样建图相当于对原来图中的点进行了平 移,但是这样平移有一个问题。举个例子,就是2+3+n和3+2+n会在同一行。这个例子不一定准确,只是说明在平移后本来一部分在原图中可以同时成立的 匹配在新图中因为没有X反倒不能同时存在了。
可以举一种简单的例子来否定这种情况,新图相当于对原图所有的X进行处理,新图中没有X,但是图的长和宽都扩大了一倍。比如说对于5*5的图(题目规定最 大值为4,这里只是举例),如果按照上面的建图方法,长和宽同时增大一倍。那么新图中最多能同时存在十个点。按照‘.’和‘X’逐个隔开的方式画图,可以 看出这种方法明显是错的。
后来想了一下,对于没有遇到城墙的点应该保留在原图,遇到一次城墙的点应该在下一个图里。对于城墙后面的点的位置不是调整到原图之后,而是完全存在一个新的图里面。所以我修改了一下建图的方法,改为当前行列数+遇到城墙数*n,修改之后提交AC。
因为对于一个n*n的图,原图的长和边的长度最多增加(n-1)*n,所以新图的点数最多应该是(n-1)*n+n,即n*n。
.X..
....
XX..
....
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <climits>
#include <queue>
#define ll long long using namespace std; const int N = ;
int head[N],total,visit[N];
int link[N],flag_x[N],flag_y[N];
char maze[][]; struct nodes
{
int e,next;
}Edge[N]; void add(int x,int y)
{
Edge[total].e = y;
Edge[total].next = head[x];
head[x] = total++;
} int dfs(int f)
{
int u = head[f];
for(int i = u; i != -; i = Edge[i].next)
{
int s = Edge[i].e;
if(visit[s]) continue;
visit[s] = ;
if(link[s] == - || dfs(link[s]))
{
link[s] = f;
return ;
}
}
return ;
} void init()
{
total = ;
memset(head,-,sizeof(head));
memset(flag_x,,sizeof(flag_x));
memset(flag_y,,sizeof(flag_y));
memset(link,-,sizeof(link));
}
int main(void)
{
int n,i,j,cnt;
while(scanf("%d",&n),n)
{
init();
for(i = ; i <= n; i++)
scanf("%s",maze[i]+); for(i = ; i <= n; i++)
{
for(j = ; j <= n ; j++)
{
if(maze[i][j] == '.')
add(n*flag_x[i]+i,n*flag_y[j]+j);
else
flag_x[i]++,flag_y[j]++;//讲城墙隔开的点建到新图里
}
}
for(cnt = ,i = ; i <= n * n; i++)
{
memset(visit,,sizeof(visit));
if(dfs(i))
cnt++;
}
printf("%d\n",cnt);
}
return ;
}
2.暴力深搜
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define PI acos(-1.0)
using namespace std;
char maps[][];
int visit[][],n,ans,k;
struct nodes
{
int x,y;
} use[];
void dfs(int th,int cur)
{
if(th >= k)
return;
dfs(th+,cur);
int x = use[th].x;
int y = use[th].y;
for(int i = y-; i >= ; i--)
{
if(maps[x][i] == 'X')
break;
if(visit[x][i] == )
{
return;
}
}
for(int i = x-; i >= ; i--)
{
if(maps[i][y] == 'X')
break;
if(visit[i][y] == )
{
return;
}
} visit[x][y] = ;
ans = max(ans,cur+);
dfs(th+,cur+);
visit[x][y] = ;
}
int main(void)
{
while(scanf("%d",&n) ,n)
{
ans = ;
k = ;
memset(visit,,sizeof(visit));
for(int i = ; i <n; i++)
scanf("%s",maps[i]);
for(int i = ; i < n; i++)
for(int j = ; j < n; j++)
{
if(maps[i][j] == '.')
use[k].x = i,use[k++].y = j;
}
dfs(,);
printf("%d\n",ans);
}
return ;
}
hdu 1045 Fire Net(二分匹配 or 暴搜)的更多相关文章
- hdu 1045 Fire Net 二分图匹配 && HDU-1281-棋盘游戏
题意:任意两个个'车'不能出现在同一行或同一列,当然如果他们中间有墙的话那就没有什么事,问最多能放多少个'车' 代码+注释: 1 //二分图最大匹配问题 2 //难点在建图方面,如果这个图里面一道墙也 ...
- HDU 1045 Fire Net(行列匹配变形+缩点建图)
题意:n*n的棋盘上放置房子.同一方同一列不能有两个,除非他们之间被墙隔开,这种话. 把原始图分别按行和列缩点 建图:横竖分区.先看每一列.同一列相连的空地同一时候看成一个点,显然这种区域不可以同一时 ...
- HDOJ(HDU).1045 Fire Net (DFS)
HDOJ(HDU).1045 Fire Net [从零开始DFS(7)] 点我挑战题目 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架/双重DFS HD ...
- HDU - 1045 Fire Net(二分匹配)
Description Suppose that we have a square city with straight streets. A map of a city is a square bo ...
- HDU 1045 Fire Net 【连通块的压缩 二分图匹配】
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others) ...
- HDU 1045 Fire Net 【二分图匹配】
<题目链接> 题目大意: 这题意思是给出一张图,图中'X'表示wall,'.'表示空地,可以放置炮台,同一条直线上只能有一个炮台,除非有'X'隔开,问在给出的图中最多能放置多少个炮台. 解 ...
- hdu 1045 Fire Net(最小覆盖点+构图(缩点))
http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit:1000MS Memory Limit:32768KB ...
- HDU 1045(Fire Net)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定大小的棋盘中部分格子存在可以阻止互相攻击的墙,问棋盘中可以放置最多多少个可以横纵攻击炮塔. [题目分析] 这题本来在搜索专题 ...
- hdu 1045:Fire Net(DFS经典题)
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
随机推荐
- 04_jQuery对象初识(三)
<div id="d1"> <p><span>span</span></p> <div>div</di ...
- 第一周课堂笔记2th
上课笔记2th https://mubu.com/doc/2gxvIvVLG0(老师笔记网址) 1. python python运行过程 把源代码转化成字节码(机器不能识别) 也可能不产生py ...
- 怎么解决VirtualBox无法安装增强工具
点击「设备」-「安装增强功能」,然后就弹出下面这个东西,百度和 bing 了很久,终于解决啦~ Unable to insert the virtual optical disk D:\Program ...
- ElasticSearch入门介绍之安装部署(二)
散仙,在上篇文章对ElasticSearch整体入门作了个介绍,那么本篇我们来看下,如何安装,部署es,以及如何安装es的几个比较常用的插件. es的安装和部署,是非常简单方便的,至少这一点散仙在es ...
- Chsh- Linux必学的60个命令
1.作用 chsh命令的作用是更改使用者shell设定,它的使用权限是所有使用者. 2.格式 chsh [ -s ] [ -list] [ --help ] [ -v ] [ username ] 3 ...
- 关于set的unordered特性
关于set排序无序的问题,原因是set使用哈希表做内存索引. 详细介绍可见: https://stackoverflow.com/questions/12165200/order-of-unorder ...
- Spring_用Spring容器创建对象并给属性赋值
创建spring配置文件:spring-config.xml.对象的创建和赋值都在这里进行配置. 创建实体类,设置属性 import java.util.List; import java.util. ...
- ALS算法实现用户音乐打分预测
很多人在决定是否看一部电影之前都会去豆瓣看下评分作为参考,看完电影也会给一个自己的分数.每个人对每个商品或者电影或是音乐都有一个心理的分数,这个分数标明用户是否对这个内容满意.作为内容的提供方,如果可 ...
- yolo-windows检测高分辨率图像及封装应用
YOLO训练自己的数据集的一些心得 封装yolo-windows为动态链接库 yolo-windows源码 项目开源代码:LargeImageDetect-yolo-windows 由于项目需要,需要 ...
- Spring AOP(一)--基本概念
AOP(Aspect Oriented Programing),意为面向切面编程,其实看了很多书本的介绍和说明,我觉得这些解释都太过书面,也可能是翻译的原因,总觉得还是不太懂,也难以理解这种叫法,尤其 ...
