LeetCode 1284. 转化为全零矩阵的最少反转次数(BFS & 矩阵状态编码解码)

1. 题目

给你一个 m x n 的二进制矩阵 mat。

每一步,你可以选择一个单元格并将它反转(反转表示 0 变 1 ,1 变 0 )。如果存在和它相邻的单元格,那么这些相邻的单元格也会被反转。(注:相邻的两个单元格共享同一条边。)

请你返回将矩阵 mat 转化为全零矩阵最少反转次数,如果无法转化为全零矩阵,请返回 -1 。

二进制矩阵的每一个格子要么是 0 要么是 1 。

全零矩阵是所有格子都为 0 的矩阵。

在这里插入图片描述

示例 1:
输入:mat = [[0,0],[0,1]]
输出:3
解释:一个可能的解是反转 (1, 0),然后 (0, 1) ,最后是 (1, 1) 。

示例 2:
输入:mat = [[0]]
输出:0
解释:给出的矩阵是全零矩阵,所以你不需要改变它。

示例 3:
输入:mat = [[1,1,1],[1,0,1],[0,0,0]]
输出:6

示例 4:
输入:mat = [[1,0,0],[1,0,0]]
输出:-1
解释:该矩阵无法转变成全零矩阵

提示:
m == mat.length
n == mat[0].length
1 <= m <= 3
1 <= n <= 3
mat[i][j]01

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. BFS解题

  • 矩阵每个格子反转操作后都可以转换成数字,检查它是否等于0(状态)
  • 先将初始状态push进队列,visited访问记录该状态(编码成数字)
  • 然后依次更改矩阵的每个位置,如果更改后的状态没出现过,push进队列
  • 遇见状态0的时候,停止BFS,返回BFS的层数,即最少反转次数
class Solution {
	vector<vector<int>> dir ={{1,0},{0,1},{0,-1},{-1,0},{0,0}};//反转操作位置
	int m, n;
public:
    int minFlips(vector<vector<int>>& mat) {
        m = mat.size(), n = mat[0].size();
        int num = matToNum(mat), step = 0, size, i, j;
        if(num == 0)
        	return step;
        unordered_set<int> visited;//访问过了的状态
        queue<int> q;
        visited.insert(num);
        q.push(num);
        while(!q.empty())
        {
        	++step;//bfs步数
        	size = q.size();
        	while(size--)
        	{
        		numToMat(q.front(),mat);//将数字解码成矩阵mat
        		q.pop();
        		for(i = 0; i < m; i++)//mat的每个位置都可以操作
        		{
        			for(j = 0; j < n; j++)
        			{   //每个位置进行反转操作
        				flip(mat,i,j);
        				num = matToNum(mat);//将矩阵状态编码成num
        				if(num == 0)
        					return step;
        				if(!visited.count(num))//这种状态没有访问过
        				{
        					visited.insert(num);//访问标记
        					q.push(num);//加入队列
        				}
        				flip(mat,i,j);//恢复现场,进行下个位置反转
        			}
        		}
        	}
        }
        return -1;
    }

    int matToNum(vector<vector<int>>& M)
    {   //矩阵编码成数字
    	int num = 0, i, j;
    	for(i = 0; i < m; i++)
    		for(j = 0; j < n; j++)
    			num = num*2+M[i][j];
		return num;
    }

    void numToMat(int num, vector<vector<int>>& M)
    {   //数字解码成矩阵
    	int bit, i, j;
    	for(i = m-1; i >= 0; i--)
    		for(j = n-1; j >= 0; j--)
    		{
    			M[i][j] = (num&1);//取最低位
    			num >>= 1;//数字右移1位
    		}
    }

    void flip(vector<vector<int>>& M, int i, int j)
    {   //反转i,j位置,及其周围4个位置
    	int x, y, k;
    	for(k = 0; k < 5; k++)
    	{
    		x = i+dir[k][0];
    		y = j+dir[k][1];
    		if(x>=0 && x<m && y>=0 && y<n)
    			M[x][y] = 1-M[x][y];
    	}
    }
};

在这里插入图片描述

发布了599 篇原创文章 · 获赞 473 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_21201267/article/details/104116933