一、题目描述
样例输入:
4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0
样例输出:
5
1
5
2
4
二、算法分析说明与代码编写指导
本题的难点在于如何建立正确的图论模型。
一行、一列同时只能有一个炮,除非被墙挡住。炮弹向上下左右发射后,直到被墙挡住之前,会摧毁经过的路径上的任何物体。
依次按照行优先或列优先的方式为一行或一列遇到墙或行 / 列末端之前的一组点编同一个号码(缩点建图),然后以行列的编号为顶点建立二分图并作二分图匹配即可。
例如样例中的第一个图
.X..
....
XX..
....
的行优先或列优先的编号结果及相应的二分图中的所有边如下(规定按列优先的编号存入二分图的时候要加 8,不难发现当城市地图不超过 4 × 4 时编号最大就为 8):
这样建图的原理是:在一个空位放置一门炮以后,从该点出发,同一行同一列遇到墙之前的任何位置都不能再放。这一条约束对应二分图匹配的性质:每一个左侧的点都只能在右侧任选一个点匹配。在不遇到墙的情况下,同一行放了两门炮对应左侧一个点连了右侧两个点;同一列放了两门炮对应左侧两个点连了右侧一个点。这两种情况在匹配的过程都是不允许出现的。
三、AC 代码
#include<cstdio>
#include<bitset>
#include<vector>
#pragma warning(disable:4996)
using namespace std;
const unsigned off = 8;
bitset<17> g[17], vis; unsigned n, m1[5][5], m2[5][5], c, match[17]; char M[7]