ccf-消除类游戏python刷题笔记
1.题目及要求
问题描述:消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地方的棋子将同时被消除。现在给你一个n行m列的棋盘,棋盘中的每一个方格上有一个棋子,请给出经过一次消除后的棋盘。请注意:一个棋子可能在某一行和某一列同时被消除。
输入格式:输入的第一行包含两个整数n, m,用空格分隔,分别表示棋盘的行数和列数。接下来n行,每行m个整数,用空格分隔,分别表示每一个方格中的棋子的颜色。颜色使用1至9编号。
输出格式:输出n行,每行m个整数,相邻的整数之间使用一个空格分隔,表示经过一次消除后的棋盘。如果一个方格中的棋子被消除,则对应的方格输出0,否则输出棋子的颜色编号。
样例输入
4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4
样例输出
2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4
评测用例规模与约定:所有的评测用例满足:1 ≤ n, m ≤ 30。
2.思路以及代码
思路:我自己的思路是先处理行,每行中有满足条件的数置零。为不影响对每列的影响,要在对行进行处理之前复制一下原始列表(存储数据的二维数组),再将每列中满足条件的数置零。将两个数组结合起来作为最后的输出。但具体处理每行(列)时逻辑不够清晰严谨,导致运行结果有的正确有的错误。
参考网上代码,比较好的一点是用字典来记标记,其中value是(i,j),即行列坐标,key初始值为0,当满足消除条件时将该坐标的key值置为1。最后在判断,如果key值为1则将该坐标的值置为0。
代码:
n,m=map(int,input().split())
a=[]
d={}
for i in range(n):
a.append(list(map(int,input().split())))
for i in range(n):
for j in range(m):
d[(i,j)]=0
# 处理行
for i in range(n):
for j in range(m-2):
if a[i][j]==a[i][j+1] and a[i][j+1]==a[i][j+2]:
d[(i,j)]=d[(i, j + 1)]=d[(i, j + 2)] =1
#处理列
for j in range(m):
for i in range(n-2):
if a[i][j]==a[i+1][j] and a[i+1][j]==a[i+2][j]:
d[(i, j)] =d[(i + 1, j)]= d[(i + 2, j)] = 1
#置0
for i in d:
if d[i] == 1:
a[i[0]][i[1]] = 0
for i in range(n):
for j in range(m):
print(a[i][j],end=' ')
print()
3.总结
通过练习这个题目,我学到了:
1.关于二维数组的创建与输入用三行代码即可实现,之前用的好几行的方法可以被上述的三行代码取代了。之前习惯用的:
a=[[]*m for i in range(n)]
for i in range(n):
list=input().split()
for j in range(m):
a[i].append(int(list[j]))
以后可以用:
a=[]
for i in range(n):
a.append(list(map(int,input().split())))
2.复制数组的时候,要使复制的数组不受原来数组改变的影响,需要使用下面的代码,之前要import copy。
a=copy.deepcopy(a)
3.这题关于字典的使用很巧妙,做标记这点不止一次遇到,可以好好品品这题的字典用法。