1. 程式人生 > >LeetCode 5282. 轉化為全零矩陣的最少反轉次數 bfs 雙向bfs

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 };
View Code

&n