LeetCode 5282. 转化为全零矩阵的最少反转次数 bfs 双向bfs

地址 https://leetcode-cn.com/submissions/detail/39277402/

题目描述
给你一个 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] 是 0 或 1 。

算法1
本题同acwing 95. 费解的开关 acwing116. 飞行员兄弟 类似

可以考虑第一层如何全零的时候 需要按那几个开关 第二层为如何全零的时候需要按那几个开关 依次推到至最后一层得到答案

在数据范围比较大的情况也可以采用 双向BFS 进行搜索范围的优化

由于范围比较小 我就采取了比较粗暴的朴素BFS
从全零的状态作为起点 依次BFS 看看走到题目给出的状态 需要几步
简单直接
用来做记录状态的key 直接使用二维数组 而没有进行压缩变形
不过代码也比较好理解
代码如下:

 1 class Solution {
 2 public:
 3
 4 map<vector<vector<int>>, int> visit;
 5 queue<pair<vector<vector<int>>, int>> q;
 6 bool CheckIsAllZero(const vector<vector<int>> &mat)
 7 {
 8     for (int i = 0; i < mat.size(); i++) {
 9         for (int j = 0; j < mat[0].size(); j++) {
10             if (mat[i][j] != 0)
11                 return false;
12         }
13     }
14
15     return true;
16 }
17
18
19 void Click(vector<vector<int>>& currenrState, int x, int y)
20 {
21     int addx[4] = { 1,-1,0,0 };
22     int addy[4] = { 0,0,-1,1 };
23
24     currenrState[x][y] = currenrState[x][y] ? 0: 1;
25
26     for (int i = 0; i < 4; i++) {
27         int newx = x + addx[i];
28         int newy = y + addy[i];
29
30         if (newx >= 0 && newx < currenrState.size() && newy >= 0 && newy < currenrState[0].size()) {
31             currenrState[newx][newy] = currenrState[newx][newy] ? 0 : 1;
32         }
33     }
34 }
35
36
37 int minFlips(vector<vector<int>>& mat) {
38     if (CheckIsAllZero(mat)) return 0;
39
40     vector<vector<int>> matAllZero(mat.size(), vector<int>(mat[0].size()));
41
42     int distance = 0;
43
44     visit[matAllZero] = distance;
45     q.push({ matAllZero ,distance });
46
47     while (!q.empty()) {
48         auto qe = q.front();
49         q.pop();
50         vector<vector<int>> currenrState = qe.first;
51         int currentCount = qe.second;
52
53         //尝试 点击该XY
54         for (int i = 0; i < currenrState.size(); i++) {
55             for (int j = 0; j < currenrState[0].size(); j++) {
56                 vector<vector<int>> copy = currenrState;
57                 Click(copy, i, j);
58
59
60                 if (copy == mat)
61                 {
62                     return currentCount + 1;
63                 }
64
65                 if (visit.count(copy) == 0) {
66                     q.push({ copy ,currentCount + 1 });
67                     visit[copy] = currentCount + 1;
68                 }
69             }
70         }
71     }
72
73
74     return -1;
75 }
76
77 };

原文地址:https://www.cnblogs.com/itdef/p/12005600.html

时间: 2024-08-28 03:19:51

LeetCode 5282. 转化为全零矩阵的最少反转次数 bfs 双向bfs的相关文章

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

https://leetcode-cn.com/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix/ DFS class Solution { private: static constexpr int dirs[5][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {0, 0}}; int ans; public: Solution(): ans(1e9) { } vo

[LeetCode] Minimum Moves to Equal Array Elements 最少移动次数使数组元素相等

Given a non-empty integer array of size n, find the minimum number of moves required to make all array elements equal, where a move is incrementing n - 1 elements by 1. Example: Input: [1,2,3] Output: 3 Explanation: Only three moves are needed (remem

LeetCode:最少移动次数使得数组元素相等||【462】

LeetCode:最少移动次数使得数组元素相等||[462] 题目描述 给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最多为10000. 例如: 输入: [1,2,3] 输出: 2 说明: 只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1): [1,2,3] => [2,2,3] => [2,2,2] 题目分析 一个直观的理解是这样的,如果我们只有两个数字的话,那么我们使得他们变成相等元素的最少步数是多

Leetcode 462.最少移动次数使数组元素相等

最少移动次数使数组元素相等 给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最多为10000. 例如: 输入: [1,2,3] 输出: 2 说明: 只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1): [1,2,3] => [2,2,3] => [2,2,2] 排序之后,从两边往中间走,最大和最小之间的差距,是一定要填补上的,不管+1 还是 -1,所以最后都等于中位数. 1 import java.uti

1、对一个正整数算到1需要的最少操作次数

题1:实现一个函数,对一个正整数n,算得到1需要的最少操作次数.操作规则为:如果n为偶数,将其除以2:如果n为奇数,可以加1或减1:一直处理下去:例子:func(7) = 4,可以证明最少需要4次运算n = 7n-1 6n/2 3n-1 2n/2 1 要求:实现函数(实现尽可能高效) int func(unsign int n):n为输入,返回最小的运算次数.给出思路(文字描述),完成代码,并分析你算法的时间复杂度. java源程序: package bfgy.lab.work; import 

数据结构实验3(飞机最少环城次数问题)

使用图算法解决应用问题: 设有n个城市, 编号为0 ~ n - 1, m条航线的起点和终点由用户输入提供. 寻找一条换乘次数最少的线路方案. 使用有向图表示城市间的航线, 只要两城市之间有航班, 则图中这两点间存在一条权为1的边. 用Dijkstra算法实现求最少换乘次数. 在MGraph类中增加Choose函数以及Dijkstra函数即可. 实现代码: #include "iostream" #include "cstdio" #include "cst

最少乘法次数

最少乘法次数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 给你一个非零整数,让你求这个数的n次方,每次相乘的结果可以在后面使用,求至少需要多少次乘.如24:2*2=22(第一次乘),22*22=24(第二次乘),所以最少共2次: 输入 第一行m表示有m(1<=m<=100)组测试数据: 每一组测试数据有一整数n(0<n<=10000); 输出 输出每组测试数据所需次数s; 样例输入 3234 样例输出 122 最少乘法次数

最少的次数

2191: 最少的次数 Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 553  Solved: 73[Submit][Status][BBS] Description 这一天,成都东软学院ACM团队举办了一场游戏.游戏是这样的: 在桌上有一堆糖,其中有一颗糖与其他糖外观一模一样,但重量却明显轻.现在得知桌上共有N颗糖,还有一个天平,问最少需要多少次一定能准确的找出该糖?今天作为比赛中的你,相信这一问题应该不是什么难事,加油吧! Input 第一行包

最少乘法次数 NYOJ 46

1 #include<stdio.h>//最少乘法次数(46) 2 int main() 3 { 4 int i,x,m; 5 scanf("%d",&x); 6 while(x--){ 7 scanf("%d",&m); 8 i=0; 9 while(m!=1){ 10 if(m%2==1){ 11 i+=2; 12 } 13 else i+=1; 14 m/=2; 15 } 16 printf("%d\n",i);