题目描述
给定一个 \(n\times m\) 的 \(01\) 矩阵,每次操作可以将某个 \(2\times2\) 的矩阵内的 \(3\) 个数取反,请在 \(n\times m\) 步内将矩阵变为全 \(0\)。
题解
这种题就是要手推数据啊!还有就是从小的情况入手,看能否拆分子问题。
对于一个\(2\times2\)的矩阵,我们发现可以用最多四次将它还原。
对于周边余下的\(1\times n\)和\(1\times m\)的数,先随便怎么还原一下。
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int f=1,j=0;
char w=getchar();
while(!isdigit(w)){
if(w=='-')f=-1;
w=getchar();
}
while(isdigit(w)){
j=j*10+w-'0';
w=getchar();
}
return f*j;
}
const int N=200;
struct act{
int x,y;
};
vector<act>mov[16];
int n,m;
void init(){
mov[1].push_back((act){2,2});mov[1].push_back((act){2,1});mov[1].push_back((act){1,2});
mov[2].push_back((act){2,1});mov[2].push_back((act){1,1});mov[2].push_back((act){2,2});
mov[3].push_back((act){1,2});mov[3].push_back((act){1,1});
mov[4].push_back((act){1,2});mov[4].push_back((act){1,1});mov[4].push_back((act){2,2});
mov[5].push_back((act){2,1});mov[5].push_back((act){1,1});
mov[6].push_back((act){2,1});mov[6].push_back((act){1,2});
mov[7].push_back((act){2,2});
mov[8].push_back((act){1,1});mov[8].push_back((act){2,1});mov[8].push_back((act){1,2});
mov[9].push_back((act){1,1});mov[9].push_back((act){2,2});
mov[10].push_back((act){1,2});mov[10].push_back((act){2,2});
mov[11].push_back((act){2,1});
mov[12].push_back((act){2,1});mov[12].push_back((act){2,2});
mov[13].push_back((act){1,2});
mov[14].push_back((act){1,1});
mov[15].push_back((act){1,1});mov[15].push_back((act){2,2});mov[15].push_back((act){2,1});mov[15].push_back((act){1,2});
return ;
}
int X[5]={0,0,0,1,-1};
int Y[5]={0,1,-1,0,0};
char s[N];
bool sum[N][N];
struct Ans{
int x[3],y[3];
}ans[N*N];
int cnt;
void deal(int a,int b,int x,int y){
a--,b--;
int tot=0;
cnt++;
for(int i=0;i<5;i++){
int xx=X[i]+x,yy=Y[i]+y;
if(xx<1||xx>2||yy<1||yy>2)continue;
ans[cnt].x[tot]=a+xx,ans[cnt].y[tot]=b+yy;
sum[a+xx][b+yy]^=1;
tot++;
}
return ;
}
void work(){
n=rd(),m=rd();
cnt=0;
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++)sum[i][j]=s[j]-'0';
}
if(n&1){
for(int i=1;i<m;i++)if(sum[n][i])deal(n-1,i,1,1);
if(sum[n][m])deal(n-1,m-1,1,2);
n--;
}
if(m&1){
for(int i=1;i<n;i++)if(sum[i][m])deal(i,m-1,1,1);
if(sum[n][m])deal(n-1,m-1,2,1);
m--;
}
// for(int i=1;i<=n+1;i++){
// for(int j=1;j<=m+1;j++)cout<<sum[i][j]<<" ";
// cout<<"\n";
// }
for(int i=1;i<=n;i+=2){
for(int j=1;j<=m;j+=2){
int sumn=0;
sumn=sumn*2+sum[i][j];
sumn=sumn*2+sum[i][j+1];
sumn=sumn*2+sum[i+1][j];
sumn=sumn*2+sum[i+1][j+1];
// cout<<i<<"-"<<j<<":"<<sumn<<"\n";
for(auto a:mov[sumn])deal(i,j,a.x,a.y);
}
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++){
for(int j=0;j<3;j++)printf("%d %d ",ans[i].x[j],ans[i].y[j]);
printf("\n");
}
return ;
}
signed main(){
init();
int T=rd();
while(T--)work();
return 0;
}
/*
1
2 2
00
11
*/
标签:cnt,int,题解,back,mov,act,push,CF1439A2
From: https://www.cnblogs.com/T-water/p/17236591.html