1284. 转化为全零矩阵的最少反转次数

题目描述

给一个二维矩阵,里面的元素不是0就是1
可以通过翻转完成0-1变换,翻转的限制是周围相邻的点也要跟着变
问最终反转成全0的形式的最小次数?

f1-状态压缩+bfs

基本分析

  1. 看大最少翻转次数可以联想到什么?bfs
  2. 直接bfs有啥问题?(1)矩阵的形式怎么存?通过状态压缩将二维转化为1维度
  3. 要实现以上需求需要做什么?定义encode函数,将mat转化为x;因为枚举翻转点的时候,有需要在mat上操作,所以需要有函数将x解码为mat
  4. 翻转的逻辑?对需要翻转的点,将点和相邻点的值^1
  5. bfs怎么保证不重?对x_cur在入队的时候进行检查,不在vis中的才入队
  6. 对每个点进行枚举之后需要注意什么?因为是本地操作,需要还原现场

代码

class Solution:
def minFlips(self, mat: List[List[int]]) -> int:
def encode(mat, m, n):
x = 0
for i in range(m):
for j in range(n):
x = x * 2 + mat[i][j]
return x
def decode(x, m, n):
mat = [[0] * n for _ in range(m)]
for i in range(m-1, -1, -1):
for j in range(n-1, -1, -1):
mat[i][j] = x & 1
x = x >> 1
return mat
def convert(mat, m, n, i, j):
for di, dj in [(-1, 0), (1, 0), (0, -1), (0, 1), (0, 0)]:
if 0 <= i + di < m and 0 <= j + dj < n:
mat[i + di][j + dj] ^= 1
m, n = len(mat), len(mat[0])
x_start = encode(mat, m, n)
if x_start == 0:
return 0
vis = {x_start}
step = 0
q = deque([x_start])
while q:
step += 1
for _ in range(len(q)):
mat = decode(q.popleft(), m, n)
for i in range(m):
for j in range(n):
convert(mat, m, n, i, j)
x_cur = encode(mat, m, n)
if x_cur == 0:
return step
if not x_cur in vis:
q.append(x_cur)
vis.add(x_cur)
convert(mat, m, n, i, j)
return -1

总结

  1. 将矩阵状态压缩为1维,这样矩阵的状态就可以去重和放进队列里面了
  2. 对点修改的时候需要考虑临近的点,这里对mat是本地操作,枚举每个修改的点之后需要还原现场
f1-状态压缩+dfs
待完善
posted @   zhangk1988  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示