题目地址:
https://www.acwing.com/problem/content/description/3231/
俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
游戏在一个 15 15 15行 10 10 10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由 4 4 4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。
输入格式:
输入的前
15
15
15行包含初始的方格图,每行包含
10
10
10个数字,相邻的数字用空格分隔。如果一个数字是
0
0
0,表示对应的方格中没有方块,如果数字是
1
1
1,则表示初始的时候有方块。输入保证前
4
4
4行中的数字都是
0
0
0。
输入的第
16
16
16至第
19
19
19行包含新加入的板块的形状,每行包含
4
4
4个数字,组成了板块图案,同样
0
0
0表示没方块,
1
1
1表示有方块。输入保证板块的图案中正好包含
4
4
4个方块,且
4
4
4个方块是连在一起的(准确的说,
4
4
4个方块是四连通的,即给定的板块是俄罗斯方块的标准板块)。
第
20
20
20行包含一个
1
1
1到
7
7
7之间的整数,表示板块图案最左边开始的时候是在方格图的哪一列中。注意,这里的板块图案指的是
16
16
16至
19
19
19行所输入的板块图案,如果板块图案的最左边一列全是
0
0
0,则它的左边和实际所表示的板块的左边是不一致的(见样例)。
方格图共
10
10
10列,从左到右依次为第
1
∼
10
1∼10
1∼10列。
输出格式:
输出
15
15
15行,每行
10
10
10个数字,相邻的数字之间用一个空格分隔,表示板块下落后的方格图。
注意,你不需要处理最终的消行。
直接枚举下落的距离,看什么时候会碰到已经存在的方块。代码如下:
#include <iostream>
using namespace std;
const int N = 30;
int g[N][N];
int t[4][4];
bool check(int row, int col) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (i + row >= 15 && t[i][j] == 1) return true;
if (g[i + row][j + col] && t[i][j]) return true;
}
}
return false;
}
int main() {
for (int i = 0; i < 15; i++)
for (int j = 0; j < 10; j++) scanf("%d", &g[i][j]);
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) scanf("%d", &t[i][j]);
int col;
scanf("%d", &col);
col--;
int k = 1;
while (k < 15) {
if (check(k, col)) break;
k++;
}
k--;
for (int i = k; i < k + 4; i++)
for (int j = col; j < col + 4; j++)
g[i][j] = t[i - k][j - col] == 0 ? g[i][j] : 1;
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 10; j++) printf("%d ", g[i][j]);
cout << endl;
}
}
时空复杂度 O ( 1 ) O(1) O(1)。