问题描述
在一个古老的实验室里,两个研究员,小星和小月,获得了一个 m x n
的电路图,表示为二进制矩阵 grid
。在这个矩阵中,他们可以对任意一个电路单元进行翻转操作。翻转操作会将所选单元的状态从 0
改为 1
,或从 1
改为 0
,同时影响与其相邻的上下左右单元。
小星和小月希望通过最少的翻转次数,将整个电路图变成全 0
的状态。如果这个目标无法实现,则返回 -1
。
测试样例
样例1:
输入:
grid = [[0, 1], [1, 0]]
输出:
2
样例2:
输入:
grid = [[1, 0], [1, 1]]
输出:
1
样例3:
输入:
grid = [[0]]
输出:
0
题解:
很经典的一道题,原题叫棋盘覆盖问题,关键在于一个位置如果翻转两次等于没有翻转。
所以直接DFS遍历每个格子,每次都有翻和不翻两个情况,最后判断翻转次数即可。
有一种更方便的方法,但是在时间上似乎不那么占优,先通过DFS生成随机1,0的长度为m*n的字符串,然后根据字符串的10,如果是1就翻转,如果是0就不翻,也不用每一位去异或,直接在对应位置+1代表翻转次数,最后遍历,如果是偶数就是0,奇数就是1即可。
代码:
cpp
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;
vector<vector<int>> grid1;
vector<vector<int>> vt;
int mincnt=100000;
int xt[5]={1,0,-1,0,0};
int yt[5]={0,1,0,-1,0};
int check(int x,int y){
int n=vt.size();
int m=vt[0].size();
if(x>=0 && x<n && y>=0 && y<m){
return 1;
}
return 0;
}
void f(int x,int y){
for(int i=0;i<5;i++){
int xx=x+xt[i];
int yy=y+yt[i];
if(check(xx,yy)){
vt[xx][yy]++;
}
}
}
void col(string s){
//cout << "YES" << "\n";
//cout << s << "\n";
int cnt=0;
for(int i=0;i<vt.size();i++){
for(int j=0;j<vt[i].size();j++){
if(s[cnt]=='1'){
//cout << "In" <<"\n";
f(i,j);
}
cnt++;
}
}
//cout << "pa1" <<"\n";
/*
for(int i=0;i<vt.size();i++){
for(int j=0;j<vt[i].size();j++){
cout << vt[i][j] << " ";
}
cout << "\n";
}
*/
bool is=true;
for(int i=0;i<vt.size();i++){
for(int j=0;j<vt[i].size();j++){
if(vt[i][j]%2!=0){
is=false;
break;
}
}
}
//cout << "pa2" << "\n";
if(is){
int ct=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
ct++;
}
}
if(ct<mincnt){
mincnt=ct;
}
}
//cout << "pa3" << "\n";
}
void dfs(string s,int num,int t){
if(num==t){
vt=grid1;
col(s);
return;
}
string a=s;
a=a+'1';
dfs(a,num+1,t);
a=s;
a=a+'0';
dfs(a,num+1,t);
}
int solution(std::vector<std::vector<int>> grid) {
vt=grid;
grid1=grid;
string s="";
mincnt=100000;
int x=grid.size();
int y=grid[0].size();
dfs(s,0,x*y);
if(mincnt==100000){
return -1;
}
return mincnt;
}
int main() {
cout << (solution({{1, 0, 1}, {0, 1, 0}, {1, 0, 1}})) << endl;
cout << (solution({{0, 1}, {1, 0}}) == 2) << endl;
cout << (solution({{1, 0}, {1, 1}}) == 1) << endl;
cout << (solution({{0, 0}, {0, 1}}) == 3) << endl;
//cout << (solution({{0}}) == 0) << endl;
return 0;
}