Fire Net
Suppose 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.
Input
The 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.
Output
For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration.
Sample Input
4 .X.. .... XX.. .... 2 XX .X 3 .X. X.X .X. 3 ... .XX .XX 4 .... .... .... .... 0
Sample Output
5 1 5 2 4
题目翻译:
假设我们有一个有直街的广场城市。城市地图是一个方形板,有n行和n列,每列代表一条街道或一块墙。
碉堡是一座小城堡,有四个开口可以射击。四个开口分别面向北,东,南和西。每个开口都会有一挺机枪射击。
在这里,我们假设子弹是如此强大,以至于它可以穿越任何距离并在途中摧毁一个碉堡。另一方面,墙壁结构坚固,可以阻止子弹。
目标是尽可能多地在城市中设置碉堡,这样就不会有两个碉堡相互摧毁。如果没有两个碉堡在地图的同一水平行或垂直列上,除非至少有一个墙将它们分开,否则碉堡的配置是合法的。在这个问题中,我们将考虑小方形城市(最多4x4),其中包含无法穿过子弹的墙壁。
下图显示了同一块板的五张图片。第一张图片是空白板,第二张和第三张图片显示合法配置,第四张和第五张图片显示非法配置。对于该板,合法配置中的最大块仓数为5;第二张图片显示了一种方法,但还有其他几种方法。
您的任务是编写一个程序,在给定地图描述的情况下,计算可以在合法配置中放置在城市中的最大数量的阻止房屋。
输入
输入文件包含一个或多个地图描述,后跟一行,其中包含表示文件末尾的数字0。每个地图描述都以包含正整数n的行开头,该正整数n是城市的大小; n最多为4.接下来的n行描述地图的一行,带有'。'表示开放空间,大写'X'表示墙。输入文件中没有空格。
输出
对于每个测试用例,输出一行,其中包含可以在合法配置中放置在城市中的最大数量的块房。
题目大意:在图中安碉堡,碉堡不能在同一行且不能在同一列,除非有‘X’隔开,最多可以安多少碉堡
思路:在同一行或同一列列且中间没有‘X'的交点看作二分图中同一个顶点,然后连边建图。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 10
#define mem(a,b) memset(a,b,sizeof(a))
int n,ch,cl,h[N][N],l[N][N],vis[N],d[N][N],f[N];
char a[N][N];
int find(int x)
{
for(int i=0; i<cl; i++)
if(vis[i]==0&&d[x][i])
{
vis[i]=1;
if(f[i]==-1||find(f[i]))
{
f[i]=x;
return 1;
}
}
return 0;
}
void hhh()
{
int ans=0;
mem(f,-1);
for(int i=0; i<ch; i++)
{
mem(vis,0);
if(find(i))ans++;
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d",&n)&&n)
{
mem(h,-1);
mem(l,-1);
mem(d,0);
for(int i=0; i<n; i++)
scanf("%s",a[i]);
ch=cl=0;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
if(a[i][j]=='.'&&h[i][j]==-1)
{
for(int k=j; a[i][k]=='.'&&k<n; k++)
h[i][k]=ch;
ch++;
}
if(a[i][j]=='.'&&l[i][j]==-1)
{
for(int k=i; a[k][j]=='.'&&k<n; k++)
l[k][j]=cl;
cl++;
}
}
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
if(a[i][j]=='.')
d[h[i][j]][l[i][j]]=1;
hhh();
}
return 0;
}