蓝桥杯-dfs-像素放置-python

蓝桥杯省赛真题-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

思路:

深度优先递归,从左上角开始,从左往右,从上往下,每次递归,每次判断,对于每个格子而言

  1. 对所有格子而言,当x,y这个格子被涂上了颜色,而它的左上角的那个格子,检查check还不能满足要求时,说明这种涂法不正确,不能往下递归,要回溯;满足了要求,才能往下递归
  2.  是最后一列的格子的时候,还得检查它的上面那个格子(因为x,y涂上颜色之后,它也被封闭上了,接下来的递归不会影响它)
  3. 如果是最后一行的格子,在最后,还得自己判断自己是否满足要求

代码:

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)



 

### 蓝桥杯 Python 实现 DFS 的示例代码及解题思路 #### 解题思路概述 在蓝桥杯竞赛中,DFS 是一种常见的算法工具,主要用于解决涉及路径探索、状态转移以及组合分配等问题。通过递归的方式实现深度优先搜索,可以有效地模拟从某个起点出发逐步深入的过程。 以下是基于引用内容和实际应用的一个典型例子——计算目标值的可能方案数[^3]: ```python # 输入处理部分 nums = list(map(int, input().split())) target = int(input()) def dfs(cur, i, d): # 如果当前索引未越界且该状态未曾被访问过,则继续向下递归 if i < len(nums) and (cur, i) not in d: d[(cur, i)] = dfs(cur + nums[i], i + 1, d) + dfs(cur - nums[i], i + 1, d) # 返回当前状态下满足条件的结果数量 return d.get((cur, i), int(cur == target)) d = {} s = dfs(0, 0, d) print(s) ``` 此代码的核心逻辑在于利用字典 `d` 来存储中间状态 `(current_sum, index)` 及其对应的计数值,从而避免重复计算并提高效率。最终返回的是能够达到目标值的所有可能性总数。 #### 关于二叉树遍历的例子 除了上述算术表达式的求解外,在数据结构领域,比如对一棵给定的二叉树执行前序、中序或者后序遍历时也可以采用类似的递归方法来完成任务[^2]。这里提供一个简单的二叉树节点定义及其相应的DFS函数作为补充说明: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def preorder_dfs(node): """ 前序遍历 """ result = [] if node is None: return result stack = [node] while stack: current_node = stack.pop() result.append(current_node.val) if current_node.right: stack.append(current_node.right) if current_node.left: stack.append(current_node.left) return result ``` 这段程序展示了如何借助栈的数据结构手动控制调用顺序以实现非递归版本的前序遍历操作。当然对于更复杂的场景还可以考虑引入辅助变量或者其他优化手段进一步提升性能表现。 #### 总结 综上所述,无论是应用于数学运算还是图形化对象的操作当中,Python 中运用 DFS 技巧都能够很好地解决问题。关键是掌握好基础概念的同时灵活调整具体实施方案适应不同需求特点。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值