https://leetcode.cn/problems/De4qBB/
这个题目比较困难的地方就是记录方阵的翻转、旋转状态
方阵的翻转,旋转和转置模板
为了能够高效的表示当前方阵的状态,我们用方阵的四个角点表示方阵当前的状态。
比如一个3×3的方阵,我们用array<pair<int, int>, 4>
来存放这个方阵的四个角,依次分别是:左上角(0,0)、右上角(0,y)、左下角(x,0)和右下角(x,y)。
翻转操作
那么他四个点的坐标就是
对应代码:
转置操作
那么他四个点的坐标就是
对应代码:
旋转操作
那么他四个点的坐标就是
对应代码(旋转可以用转置+翻转来实现):
可以从上面看出来,对图形的操作,就可以表示为对四个角的二维方阵的操作。
因为翻转之后,我们需要知道新的图形的x,y的坐标轴的变化,比如
这个图形旋转之前的坐标轴的单位变化分别是dx=(1,0)和dy=(0,1),顺时针旋转90度之后的单位变化dx=(0,1),dy=(−1,0)。
为了方便记录当前的单位变化dx和dy,我们在每次翻转、旋转和转置的时候,重新计算一次dx和dy。计算的代码如下:
那么最终,我们就可以通过左上角的坐标,和单位坐标的变化dx和dy,来映射得到原始的坐标。
代码如下所示:
那么最终完整的矩阵模板:
本题的实现
前置内容
我们首先设计了6个位置,就是立方体的展开图。如下所示:
我们把位置按照这个形状进行设计,是因为可以和方便的计算他的相邻边。具体可看后面相邻边的数字变化。
然后定义每个矩阵的边的顺序【0,1,2,3】,依次是【上,右,下,左】。
比如0号位置的下方和2号位置的上方相邻,就构成一个边的四元组「0号位置,2号位置,下方,上方」,[0, 2, 2, 0]。
比如0号位置的左边和1号位置的上方相邻,就构成一个边的四元组「0号位置,1号位置,左边,上方」,[0, 1, 3, 0]。
那么写出0号位置所相邻边的四元组:
然后是5号位置相邻边的四元组:
然后就是其他四条边:
为了按照顺序获取方阵的四条边,我们先定义了个方阵,然后逆时针旋转四次,每次旋转,获取一次当前位置的第一条边。
题目思路
我们本题使用搜索检查每个位置是否满足。首先固定第一个方阵,我们把它固定放在0位置。然后每个位置尝试将其他的方阵旋转或者翻转放入。
对于立体图形的边,我们要求不能相邻的边在同一个位置具有相同的元素。
对于立体图形的角,我们要求不能两个边同时出现1,为了避免三个相邻面共享的同一个角都是0,我们一开始就先计算1个总个数,要求1个总个数刚刚好。
完整代码如下:
最后打印一下第一个样例的匹配情况: