蓝桥杯省赛真题-DFS-像素放置
题目:
小蓝最近迷上了一款名为《像素放置》的游戏,游戏在一个n xm 的网格棋盘上进行,棋盘含有几 行,每行包含 m 个方格。玩家的任务就是需要对这 n x m 个方格进行像素填充,填充颜色只有黑色或白色两种。有些方格中会出现一个整数数字 æ(0 < ル < 9),这表示当前方格加上周围八个方向上相邻的方格(分别是上方、下方、左方、右方、左上方、右上方、左下方、右下方)共九个方格内有且仅有 个方格需要用黑色填充。
玩家需要在满足所有数字约束下对网格进行像素填充,请你帮助小蓝来完成。题目保证所有数据都有解并且解是唯一的。
输入格式:
输入的第一行包含两个整数 n,m,用一个空格分隔,表示棋盘大小。
接下来 几 行,每行包含 m 个字符,表示棋盘布局。字符可能是数字0 ~ 9,这表示网格上的数字;字符还有可能是下划线(ASCI码为 95),表示一个不带有数字的普通网格。
6 8
_1__5_1_
1_4__42_
3__6__5_
___56___
_688___4
_____6__
输出格式:
输出 n 行,每行包含 m 个字符,表示答案。如果网格填充白色则用字符 0表示,如果网格填充黑色则用字符 1 表示
00011000
00111100
01000010
11111111
01011110
01111110
思路:
深度优先递归,从左上角开始,从左往右,从上往下,每次递归,每次判断,对于每个格子而言
- 对所有格子而言,当x,y这个格子被涂上了颜色,而它的左上角的那个格子,检查check还不能满足要求时,说明这种涂法不正确,不能往下递归,要回溯;满足了要求,才能往下递归
- 是最后一列的格子的时候,还得检查它的上面那个格子(因为x,y涂上颜色之后,它也被封闭上了,接下来的递归不会影响它)
- 如果是最后一行的格子,在最后,还得自己判断自己是否满足要求
代码:
import sys
n, m = map(int, input().split())
v = [[0 for _ in range(m+1)]]
for i in range(n):
a = ['0'] + list(input())
for j in range(len(a)):
if a[j] == '_':
a[j] = -1
else:
a[j] = int(a[j])
v.append(a)
ans = [[-1 for _ in range(m+1)] for _ in range(n+1)]
def get(x, y): # 获取一个位置附近的黑色网格数
cnt = 0
for dx in range(-1, 2):
for dy in range(-1, 2):
tx, ty = dx+x, dy+y
if 1<=tx<n+1 and 1<=ty<m+1:
if ans[tx][ty] == 1:
cnt += 1
return cnt
def check(x,y): # 检查当前状态,能不能使x,y这个位置满足要求
if v[x][y] == -1:
return True
else:
return v[x][y] == get(x,y)
# 深度优先递归,从左上角开始,从左往右,从上往下,每次递归,每次判断,对于每个格子而言
# 对所有格子而言,当x,y这个格子被涂上了颜色,而它的左上角的那个格子,检查check还不能满足要求时,说明这种涂法不正确,不能往下递归,要回溯;满足了要求,才能往下递归
# 1. 是最后一列的格子的时候,还得检查它的上面那个格子(因为x,y涂上颜色之后,它也被封闭上了,接下来的递归不会影响它)
# 2. 如果是最后一行的格子,在结尾,还得自己判断自己是否满足要求
def dfs(x1,y1):
if x1 == n+1: # 检查最后一行
for j in range(1,m+1):
if not check(x1-1,j): # 不行就回溯
return
for i in range(1, n + 1):
for j in range(1, m + 1):
print(ans[i][j], end='')
print()
sys.exit(0)
if y1 == m: # 最后一列的格子,左上角和直上方的格子要检查,递归之后是到下一行的第一个格子
ans[x1][y1] = 0
if x1 > 1: # 第一行的,不存在左上角和直上方的格子要检查,直接递归
if check(x1-1,y1-1) and check(x1-1,y1):
dfs(x1+1,1)
else: # 不是第一行的,要检查左上角和直上方的格子,然后检查满足才能递归
dfs(x1+1,1)
ans[x1][y1] = 1
if x1 > 1: # 第一行的,不存在左上角和直上方的格子要检查,直接递归
if check(x1 - 1, y1 - 1) and check(x1 - 1, y1):
dfs(x1 + 1, 1)
else: # 不是第一行的,要检查左上角和直上方的格子,然后检查满足才能递归
dfs(x1 + 1, 1)
return
# 对普通格子的处理
ans[x1][y1] = 0 # 先试着涂成白色的
if x1 > 1 and y1 > 1: # 第一行或第一列不测左上
if check(x1 - 1, y1 - 1):
dfs(x1, y1 + 1)
else:
dfs(x1, y1 + 1)
ans[x1][y1] = 1 # 如果涂成白色的不能满足要求,就会回溯,然后涂成黑色的,再去递归
if x1 > 1 and y1 > 1: # 第一行或第一列不测左上
if check(x1 - 1, y1 - 1):
dfs(x1, y1 + 1)
else:
dfs(x1, y1 + 1)
dfs(1,1)