题目描述:点击进入
题意
给你一个大小为n×m的二进制表,这个表由符号 0 和符号 1 组成。
你可以进行这样的操作:
选择属于一个 2 × 2 正方形的 3 个不同的单元格,并更改这些单元格中的符号(将 0 更改为1, 1 更改为 0 )。
你的任务是使表中的所有符号都等于0。您最多可以进行 nm次 操作。
你不需要最小化操作的数量。
思路
这是上一题的加强版,操作次数变为 nm 了,我上一次的代码过不去,无奈只能优化,但也只是对边界处理优化了一下,却神奇过了(神奇神奇,用xy哥的话来说那就是可蒸馏啊)
优化:边界特判的时候由看包含边界整个 2*2 矩形变为只看边界线,可以减少一些操作次数
代码
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define INF 0x3f3f3f3f
#define pii pair<int, int>
//#define pdi pair<double,int>
//#define int long long
using namespace std;
typedef long long ll;
typedef unsigned long long llu;
const int maxn=1e5+10;
const int mod=1000000007;
int t,n,k,m,tot;
vector<int>ax;
vector<int>ay;
char a[110][110];
int check(int x,int y)
{
int sum=0;
for(int i=x;i<=x+1;i++)
{
for(int j=y;j<=y+1;j++)
{
if(a[i][j]=='0')
sum++;
}
}
return sum;
}
void check1(int x,int y)
{
for(int i=x;i<=x+1;i++)
{
for(int j=y;j<=y+1;j++)
{
if(a[i][j]=='1')
{
ax.push_back(i);
ay.push_back(j);
a[i][j]='0';
}
}
}
}
void check2(int x,int y)
{
int flag=1;
for(int i=x;i<=x+1;i++)
{
for(int j=y;j<=y+1;j++)
{
if(a[i][j]=='0'||a[i][j]=='1'&&flag)
{
if(a[i][j]=='1') flag--;
ax.push_back(i);
ay.push_back(j);
if(a[i][j]=='0') a[i][j]='1';
else a[i][j]='0';
}
}
}
check1(x,y);
}
void check3(int x,int y)
{
int flag=2;
for(int i=x;i<=x+1;i++)
{
for(int j=y;j<=y+1;j++)
{
if(flag&&a[i][j]=='0'||a[i][j]=='1')
{
if(a[i][j]=='0') flag--;
ax.push_back(i);
ay.push_back(j);
if(a[i][j]=='0') a[i][j]='1';
else a[i][j]='0';
}
}
}
check2(x,y);
}
void check0(int x,int y)
{
int flag=3;
for(int i=x;i<=x+1;i++)
{
for(int j=y;j<=y+1;j++)
{
if(flag)
{
flag--;
ax.push_back(i);
ay.push_back(j);
a[i][j]='0';
}
}
}
check3(x,y);
}
int main( )
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
ax.clear();
ay.clear();
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
if(m&1)
{
for(int i=1;i<=n-1;i+=2)
{
int cnt=0;
if(a[i][m]=='1')
{
cnt++;
a[i][m]='0';
ax.push_back(i);
ay.push_back(m);
}
if(a[i+1][m]=='1')
{
cnt++;
a[i+1][m]='0';
ax.push_back(i+1);
ay.push_back(m);
}
if(cnt==0) continue;
else if(cnt==1)
{
if(a[i][m-1]=='0') a[i][m-1]='1';
else a[i][m-1]='0';
ax.push_back(i);
ay.push_back(m-1);
if(a[i+1][m-1]=='0') a[i+1][m-1]='1';
else a[i+1][m-1]='0';
ax.push_back(i+1);
ay.push_back(m-1);
}
if(cnt==2)
{
if(a[i][m-1]=='0') a[i][m-1]='1';
else a[i][m-1]='0';
ax.push_back(i);
ay.push_back(m-1);
}
}
}
if(n&1)
{
for(int j=1;j<=m-1;j+=2)
{
int cnt=0;
if(a[n][j]=='1')
{
cnt++;
a[n][j]='0';
ax.push_back(n);
ay.push_back(j);
}
if(a[n][j+1]=='1')
{
cnt++;
a[n][j+1]='0';
ax.push_back(n);
ay.push_back(j+1);
}
if(cnt==0) continue;
else if(cnt==1)
{
if(a[n-1][j]=='0') a[n-1][j]='1';
else a[n-1][j]='0';
ax.push_back(n-1);
ay.push_back(j);
if(a[n-1][j+1]=='0') a[n-1][j+1]='1';
else a[n-1][j+1]='0';
ax.push_back(n-1);
ay.push_back(j+1);
}
if(cnt==2)
{
if(a[n-1][j]=='0') a[n-1][j]='1';
else a[n-1][j]='0';
ax.push_back(n-1);
ay.push_back(j);
}
}
}
for(int i=1;i<=n-1;i+=2)
{
for(int j=1;j<=m-1;j+=2)
{
int sum=check(i,j);
if(sum==4) continue;
else if(sum==3)
check3(i,j);
else if(sum==2)
check2(i,j);
else if(sum==1)
check1(i,j);
else if(sum==0)
check0(i,j);
}
}
for(int i=1;i<=n-1;i++)
{
for(int j=1;j<=m-1;j++)
{
int sum=check(i,j);
if(sum==4) continue;
else if(sum==3)
check3(i,j);
else if(sum==2)
check2(i,j);
else if(sum==1)
check1(i,j);
else if(sum==0)
check0(i,j);
}
}
int len=ax.size();
cout<<len/3<<endl;
for(int i=0;i<len;i+=3)
{
cout<<ax[i]<<' '<<ay[i]<<' '<<ax[i+1]<<' '<<ay[i+1]<<' '<<ax[i+2]<<' '<<ay[i+2]<<' '<<endl;
}
}
return 0;
}