# 1284 - Minimum Number of Flips to Convert Binary Matrix to Zero Matrix
###### tags: `Hard`
* Question:
https://leetcode.com/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix/
1.可以選擇矩陣中的一個元素及它的上下左右元素進行翻轉(flip)
2.翻轉兩次又回到原點
3.題目輸入矩陣大小不超過3x3,所以可以直接暴力解
* Reference:
https://hackmd.io/@Zero871015/LeetCode-1284
Key:
1. Brute force
2. BFS
以翻轉次數作為level,先設定queue跟visited來將要檢查和翻轉的矩陣丟入queue中,檢查過的就丟入visited,為了產生n次翻轉的所有可能矩陣,每次迴圈(first for loop)結束就代表第i次可能已經遍尋完,且翻轉結果也存到queue中。
翻轉則是使用兩個for loop控制行和列位置來翻轉。
最後queue沒有矩陣就代表,所有結果已經遍尋完,裡面沒有zero matrix。
## Brute force solution
```cpp=
class Solution {
public:
//TODO: For debug, show the matrix context.
void show(vector<vector<int>>& mat)
{
int sx = mat[0].size();
int sy = mat.size();
for(int i = 0; i < sy; i++)
{
for(int j = 0; j < sx; j++)
cout << mat[i][j] << " ";
cout << endl;
}
}
//TODO: Flip the cell you chosen and its neighboors.
void trigger(vector<vector<int>>& mat,int x, int y)
{
int sx = mat[0].size() - 1;
int sy = mat.size() - 1;
mat[y][x] ^= 1;
if(x != 0) mat[y][x-1] ^= 1;
if(y != 0) mat[y-1][x] ^= 1;
if(x !=sx) mat[y][x+1] ^= 1;
if(y !=sy) mat[y+1][x] ^= 1;
}
//TODO: Check the matrix is equal to zero or not.
bool isZero(vector<vector<int>> mat)
{
int sx = mat[0].size();
int sy = mat.size();
for(int i = 0; i < sy; i++)
{
for(int j = 0; j < sx; j++)
if(mat[i][j]!=0) return false;
}
return true;
}
int findMin(vector<vector<int>>& mat)
{
int sx = mat[0].size();
int sy = mat.size();
int min = 100;
for(int k = 1; k < pow(2,sx*sy); k++)
{
vector<vector<int>> tempMat = mat;
int temp = k;
int count = 0;
int score = 0;
while(temp != 0)
{
if(temp%2==1)
{
trigger(tempMat,count%sx,count/sx);
score++;
}
temp/=2;
count++;
}
if(isZero(tempMat))
min = min<score?min:score;
}
return min==100?-1:min;
}
int minFlips(vector<vector<int>>& mat) {
if(isZero(mat)) return 0;
//show(mat);
return findMin(mat);
}
};
```
## BFS Solution
```cpp=
class Solution {
public:
int minFlips(vector<vector<int>>& mat) {
// Check corner cases
int m = mat.size();
int n = m ? mat[0].size() : 0;
if(m < 1 or n < 1) { return -1; }
// Prepare for BFS
set<vector<vector<int>>> visited;
queue<vector<vector<int>>> q;
q.push(mat);
visited.insert(mat);
int steps = 0;
while(!q.empty()) {
for(int sz = q.size() - 1; sz >= 0; --sz) {
vector<vector<int>> cur = q.front();
q.pop();
// 已經成功翻成全部都是 0
if(allZero(cur)) {
return steps;
}
for(int r = 0; r < m; ++r) {
for(int c = 0; c < n; ++c) {
// 以 (r,c) 為中心翻一次 matrix
flip(cur, m, n, r, c);
// 如果還沒走過這個盤面,放入 queue
if(!visited.count(cur)) {
q.push(cur);
visited.insert(cur);
}
// 把盤面翻回來
flip(cur, m, n, r, c);
}
}
}
++steps;
}
return -1;
}
private:
void flip(vector<vector<int>>& mat, int& m, int& n, int& r, int& c) {
// 翻鄰居
if(r - 1 >= 0) { mat[r-1][c] = (mat[r-1][c] == 1) ? 0 : 1; }
if(r + 1 < m) { mat[r+1][c] = (mat[r+1][c] == 1) ? 0 : 1; }
if(c - 1 >= 0) { mat[r][c-1] = (mat[r][c-1] == 1) ? 0 : 1; }
if(c + 1 < n) { mat[r][c+1] = (mat[r][c+1] == 1) ? 0 : 1; }
// 翻(r,c)
mat[r][c] = (mat[r][c] == 1) ? 0 : 1;
}
//the only purpose is checking the mat is zero or not, so use const to avoid changing the mat
bool allZero(const vector<vector<int>>& mat) {
for(int i = 0; i < mat.size(); ++i) {
for(int j = 0; j < mat[0].size(); ++j) {
if(mat[i][j] != 0) {
return false;
}
}
}
return true;
}
};
```