题意: 有一个nm的01矩阵,每次操作可选其中2 * 2子矩阵的任意3个元素取反,要求将所有元素变成0,且操作次数在3n*m以内(保证存在答案)。
输出操作的总次数及每次操作对应的元素下标。
思路: 分两个部分处理 (100+行的模拟,比赛的时候wa了6发,我直接呜呜了)
- 先暴力处理前(n-1)*m个位置,即每次把’1’放在正反L的’头’(即上一层单出来那个)。
- 再单独处理最后一层,每次都看第j和j+1个位置。将是’11’型,'10’型和最后一个元素’01’型分类讨论。
- 这样修改次数约为n*m+次(最后一行的操作次数较多)。
代码实现:
#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ll long long
#define int long long
#define pii pair<int, int>
#define lowbit(x) (x &(-x))
#define ls(x) x<<1
#define rs(x) (x<<1+1)
#define me(ar) memset(ar, 0, sizeof ar)
#define mem(ar,num) memset(ar, num, sizeof ar)
#define rp(i, n) for(int i = 0, i < n; i ++)
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define pre(i, n, a) for(int i = n; i >= a; i --)
#define IOS ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int way[4][2] = {
{
1, 0}, {
-1, 0}, {
0, 1}, {
0, -1}};
using namespace std;
const int inf = 0x7fffffff;
const double PI = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1e9 + 7;
const int N = 2e5 + 5;
int t, n, m;
char s[110][110];
int mp[110][110];
int x1[N], y1[N], x2[N], y2[N], x3[N], y3[N];
signed main()
{
IOS;
cin >> t;
while(t --){
cin >> n >> m;
for(int i = 0; i < n; i ++)
cin >> s[i];
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
mp[i][j] = s[i-1][j-1]-'0';
int cnt = 0; //先把前n-1行的1都处理了
for(int i = 1; i < n; i ++){
for(int j = 1; j <= m; j ++){
if(mp[i][j]){
mp[i][j] = !mp[i][j];
if(j==1){
// 1
mp[i+1][j] = !mp[i+1][j]; // 11
mp[i+1][j+1] = !mp[i+1][j+1];
x1[++cnt] = i, y1[cnt] = j;
x2[cnt] = i+1, y2[cnt] = j; //下
x3[cnt] = i+1, y3[cnt] = j+1; //右下
}
else{
mp[i+1][j] = !mp[i+1][j];
mp[i+1][j-1] = !mp[i+1][j-1];
x1[++cnt] = i, y1[cnt] = j;
x2[cnt] = i+1, y2[cnt] = j; //下 // 1
x3[cnt] = i+1, y3[cnt] = j-1; //左下 // 11
}
// //debug
// cout << "cnt:" << cnt << endl;
// for(int k = 1; k <= n; k ++){
// for(int l = 1; l <= m; l ++)
// cout << mp[k][l];
// cout <<endl;
// }
}
}
}
//再来处理最后一行,没次都两个两个考虑(放在2*2矩阵中)
for(int j = 1; j <= m; j ++){
if(mp[n][j]){
//如果遍历最后一行时遇到了1
if(j<m){
//且它不是最后一个
if(mp[n][j+1]){
x1[++cnt] = n, y1[cnt] = j; //自
x2[cnt] = n-1, y2[cnt] = j; //上 // 00
x3[cnt] = n-1, y3[cnt] = j+1; //右上 // 11
x1[++cnt] = n-1, y1[cnt] = j; //上
x2[cnt] = n-1, y2[cnt] = j+1; //右上
x3[cnt] = n, y3[cnt] = j+1; //右
j ++;
}
else{
x1[++cnt] = n, y1[cnt] = j; //自
x2[cnt] = n-1, y2[cnt] = j; //上
x3[cnt] = n, y3[cnt] = j+1; //右
// 00
x1[++cnt] = n, y1[cnt] = j; //自 // 10
x2[cnt] = n-1, y2[cnt] = j; //上
x3[cnt] = n-1, y3[cnt] = j+1; //右上
x1[++cnt] = n, y1[cnt] = j; //自
x2[cnt] = n, y2[cnt] = j+1; //右
x3[cnt] = n-1, y3[cnt] = j+1; //右上
}
}
else{
x1[++cnt] = n, y1[cnt] = j; //自
x2[cnt] = n, y2[cnt] = j-1; //左
x3[cnt] = n-1, y3[cnt] = j; //上
// 00
x1[++cnt] = n, y1[cnt] = j; //自 // 01
x2[cnt] = n-1, y2[cnt] = j; //上
x3[cnt] = n-1, y3[cnt] = j-1; //左上
x1[++cnt] = n, y1[cnt] = j; //自
x2[cnt] = n, y2[cnt] = j-1; //左
x3[cnt] = n-1, y3[cnt] = j-1; //左上
}
}
}
cout << cnt << endl;
for(int i = 1; i <= cnt; i ++)
cout << x1[i] << " " << y1[i] << " " << x2[i] << " " << y2[i] << " " << x3[i] << " " << y3[i] <<endl;
}
return 0;
}