Python题解—方格分隔

题目描述

给定一个6×6 的方格,沿着格子的边线剪开成两部分。 要求这两部分的形状完全相同。

如下就是三种可行的分割法。

图片描述

图片描述

图片描述

试计算: 包括这 3 种分法在内,一共有多少种不同的分割方法。 注意:旋转对称的属于同一种分割法。

问题分析:

​ 已知:一个由方块组成的正方形

​ 未知:怎么分隔能获得两个形状相同的方块

​ 首先是进行问题的转化,根据正方形的对称性,其实我们分隔方块只要考虑一半:从中心点引出一条割出去的线。找到一共有多少个这样的线,再根据正方形的对称性,除以4,就可以得到一共有多少种这样的线。

​ 所以目前问题就变为了:从中心点开始搜索,一共能找到多少个出去的线?

​ 经过仔细考虑,我们不难发现,这里面还有很多的限制条件:

  1. 一条线不能经过已经走过的位置。

  2. 一条线不能经过已经走过的关于原点对称的位置,这是因为这会对你的另一半分隔产生影响。

    如果不考虑这些因素,循环将无限下去,因为它会在里面绕圈圈。

方案拟定:

  1. 存储:使用二维数组来存储是否走过的标识。计数器count。dir二维数组存储搜索方向。
  2. 采用dfs进行搜索:
    1. 确定结束条件:到达边界点,这代表这条线已经画完了,count加一
    2. 约束条件:不能走到被标记的地方
    3. 搜索过程中要干的事?没有,本题仅仅是探索有多少条线,中间并不需要干事。
    4. 深度优先搜索:向四个方向进行搜索
    5. 标记:本题的标记在进行回溯的时候,应该要消除的,从而免除对其他搜索的影响。这一步也是为什么我没做出来这道题的原因,我们需要对还原有着敏感的认知。
# 计数器
count = 0
# 遍历的方向
dir = [[0, 1], [0, -1], [1, 0], [-1, 0]]
# 所走位置的标识
flag = [[0 for i in range(7)] for j in range(7)]

# 深度优先遍历
def dfs(x, y):
	# x, y为搜索的位置
    
    global count
    
    # 约束条件
    if flag[x][y] == 1:
        return
    
    # 终止条件
    if x == 0 or y == 0 or x == 7 or y == 7:
        count += 1
        return
    
    # 标识
    flag[x][y], flag[6 - x][6 - y] = 1, 1
    
    # 进行下一阶段的搜索
    for i in range(4):
        newx = x + dir[i][0]
        newy = y + dir[i][1]
        
        dfs(newx, newy) # 这里不能有return,否则不会进行回溯,也无法向四个方向搜索了
	
    # 还原标识
    flag[x][y], flag[6 - x][6 - y] = 0, 0

回顾反思:

  1. 对于dfs中return的使用,如果要进行回溯。则不能使用。
  2. 在一个回溯中,我们可以通过还原标识的方法,来消除对其他遍历的影响
  3. 用树来理解dfs是有帮助的
  4. 搜索就是搜索,没必要强加一些无用的东西
posted @ 2022-04-03 11:30  潮自生  阅读(118)  评论(0)    收藏  举报