给定$n,w,h$,求在$n \times n$的网格中,最多能放入几种宽和高不超过$w和h$的连通块。其中一个连通块经过平移、旋转和翻转得到的连通块不属于新的连通块。
链接
题目链接:Uva1602-Lattice Animals
参考链接:XDU_Skyline’s Blog,Rujia Liu’s Github Repository
题解
分为两部分,一部分为搜索,另一部分为判重。
搜索可以采用BFS也可以采用DFS。示例代码里采用了BFS。
判重部分,因为一个连通块经过平移、旋转和翻转后得到的连通块不属于新的连通块,所以在判断一个连通块是否重复时首先要对其每一种可能的形态进行判断。
对于平移操作,我们考虑将连通块进行标准化normalize,即统计连通块的x方向和y方向的最小值minX和minY,然后将连通块中的每一个单元格都减去矢量(minX,minY)得到标准化后的连通块。
对于旋转操作,假设一个单元格的坐标为(x,y),表示逆时针旋转90°的旋转矩阵为
$$
\begin{bmatrix}
0 & -1 \\
1 & 0
\end{bmatrix}
$$
所以该单元格逆时针旋转90°之后的坐标为(-y, x)。对连通块中的每一个单元格都执行此操作就得到了旋转后的连通块。旋转之后的连通块还要进行一次normalize操作再判重。
对于翻转操作,可以沿x轴翻转也可以沿y轴翻转。其对应的坐标变换是(x,y)->(-x,y)。(以沿y轴翻转为例)。翻转之后还要进行一圈的旋转判重,事实上沿x轴进行翻转后再旋转180°就可以得到沿y轴翻转后的图形,所以不需要再分开讨论这两种不同的翻转情况。同样翻转之后的连通块也要进行normalize操作后再判重。
以上是思路部分,关于具体的实现,搜索部分采用BFS,判重部分利用STL中的set判重。单元格通过一个结构体存储x和y坐标来表示,联通块通过set存储其各个单元格来表示。连通块之所以用set表示,而不是vector,是因为set会自动排序,这样就避免了因插入顺序不同导致的判重失败问题。
代码
1 | /* |