题目:在n*n的方格里,放入几个喷火器,他们会攻击同行、同列的点,问做多能放多少个。
分析:图论,搜索,二分图匹配。本题可以利用搜索求解,这里我使用的是二分图匹配。
建图,把原图每行每列的不同的连续区间分别看成一个新图中的点xi与yj;
则边<xi,yj>表示原图中对应位置的点,原图中可以互相攻击的点就对应到新图中相同的xi与yj;
则新图中的二分图最大匹配即为,原图中不能相互攻击的最大摆放数量。
说明:图论关键就是建图。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
char maps[5][5];
int g[17][17];
int line[5][5],row[5][5];
int used[17],link[17];
int dfs(int s, int n)
{
for (int i = 0 ; i <= n ; ++ i)
if (g[s][i] && !used[i]) {
used[i] = 1;
if (link[i] == -1 || dfs(link[i], n)) {
link[i] = s;
return 1;
}
}
return 0;
}
int main()
{
int n,x,y;
while (~scanf("%d",&n) && n) {
for (int i = 0 ; i < n ; ++ i)
scanf("%s",maps[i]);
memset(line, -1, sizeof(line));
memset(row, -1, sizeof(row));
int line_count = -1,row_count = -1;
for (int i = 0 ; i < n ; ++ i)
for (int j = 0 ; j < n ; ++ j) {
if (j == 0 || maps[i][j] != '.')
line_count ++;
if (maps[i][j] == '.')
line[i][j] = line_count;
if (j == 0 || maps[j][i] != '.')
row_count ++;
if (maps[j][i] == '.')
row[j][i] = row_count;
}
memset(g, 0, sizeof(g));
for (int i = 0 ; i < n ; ++ i)
for (int j = 0 ; j < n ; ++ j)
if (maps[i][j] == '.')
g[line[i][j]][row[i][j]] = 1;
int sum = 0;
memset(link, -1 ,sizeof(link));
for(int i = 0 ; i <= line_count ; ++ i) {
memset(used, 0, sizeof(used));
sum += dfs(i, row_count);
}
printf("%d\n",sum);
}
return 0;
}