你入侵了一个特别版的俄罗斯方块(Tetris)游戏,该版本允许你自由选择下一个出现的方块。你的目标不再是生存,而是创作像素艺术。
- 游戏区域是一个 $h \times w$ 的矩形网格,初始为空。左上角为 $(0, 0)$,右下角为 $(h, w)$。保证 $w$ 是奇数。
- 在触发游戏结束(Game Over)之前,方块最多可以在可见网格上方堆叠 20 行。
- 共有 7 种四格骨牌(tetromino),每种由 4 个相连的方块组成,根据其独特的形状命名为:I、J、L、O、S、T 和 Z。下图展示了这 7 种四格骨牌的 4 种朝向。第一列显示初始朝向,之后的每一列都是将前一列绕方块中心(用白圈表示)顺时针旋转 $90^\circ$ 得到的。
- 在每一步中,你可以指定一个三元组 $(t, x, d)$,其中 $t$ 是一个大写字母,$x, d$ 是整数。接着,一个方块 $t$ 将会显现,它由初始朝向逆时针旋转 $d \times 90^\circ$ 得到,其中心坐标四舍五入到最近的整数后,初始时为 $(-\infty, x)$。该方块将向下下落,直到碰撞到网格底部或区域中的任何其他方块,并固定为网格中的方块。
- 消行(Line Clear):当某一个水平行被方块完全填满时,它会消失。被消除行上方的所有方块都会向下移动一行。
给你一个与游戏区域大小相同的网格,代表一个像素艺术图案。你的任务是构建一个移动序列,使得在执行这些移动后,网格中所有 '#' 的位置都被方块占据,而 '.' 的位置为空。
输入格式
每个测试点包含多个测试用例。
第一行包含测试用例的数量 $T$ ($1 \le T \le 10^4$)。
每个测试用例的第一行包含两个整数 $1 \le h \le 100$ 和 $w \le 100$,其中保证 $w$ 为奇数。
接下来的 $h$ 行,每行包含一个长度为 $w$ 的字符串,由 '.' 和 '#' 组成,代表目标图案。
保证所有测试用例中 $hw$ 的总和不超过 $10^5$。
输出格式
对于每个测试用例:
如果无解,输出 -1。否则,第一行应包含一个整数 $0 \le k \le 10hw$,表示你构建的方案中的操作步数。
接下来的 $k$ 行,每行包含一个大写字母 $t$,后跟两个整数 $x$ 和 $0 \le d \le 3$,代表一次移动 $(t, x, d)$。
可以证明,如果存在解,则必然存在一个操作步数不超过 $10hw$ 的解。
样例
输入样例 1
2 3 5 ..... ..#.. .###. 3 5 ..#.. ..... #...#
输出样例 1
1 T 3 0 -1
说明
我们提供了一个评测程序(checker)来帮助你在本地验证解决方案的正确性。(提示:你可以从 checker.cpp 中复制一些代码片段来编写你自己的解决方案。)
编译
将 checker.cpp 和 testlib.h 放在同一个目录下,然后使用以下命令编译:
g++ checker.cpp -o checker
若要启用详细模式(在每步移动后打印游戏区域),请添加 -DVERBOSE 标志:
g++ checker.cpp -o checker -DVERBOSE
使用方法
使用以下命令运行评测程序:
./checker <input-file> <output-file> <answer-file>