思维+枚举B. Putting Bricks in the Wall
解题思路
题目说最多只要改变两个格子的数就可以封住路,中间乱七八糟的肯定考虑不来,所以考虑特殊的点——起点(或者终点也可以)。只要把起点封住就走不出来了。
可以封成两种情况,涉及到5个点。手推一下,不管什么情况,如果是一开始没被封住,那么最多只需要改变2个点就能变成下面的情况之一。
情况一:
s | 0 | 1 |
---|---|---|
0 | 1 | |
1 |
情况二:
s | 1 | 0 |
---|---|---|
1 | 0 | |
0 |
判断的时候后来发现直接枚举就行了,去枚举两种情况下需要改变的次数,满足 c n t < = 2 cnt <= 2 cnt<=2 就输出结果。如果两种情况都不满足,说明不需要改变,输出 0 0 0。
参考代码
#include<bits/stdc++.h>
using namespace std;
//#define LOCAL //提交的时候一定注释
#define _for(i, a, b) for(int i = (a); i < (b); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define pb push_back
#define VI vector<int>
#define maxn 300
#define INF 0x3f3f3f3f
typedef long long LL;
typedef double db;
const double eps = 1e-6; //定义浮点数误差
const int MOD = 998244353;
int readint(){
int x; scanf("%d", &x); return x;
}
int num[maxn][maxn];
bool solve(int flag) {
int cnt = 0;
//2个的变1
vector<pair<int, int> > ans;
for(int i = 0, j = 1; i <= 1, j >= 0; i++, j--) {
// cnt += num[i][j] ^ 1;
if (num[i][j] == flag) {
cnt++;
ans.pb(make_pair(i, j));
}
}
for(int i = 0, j = 2; i <= 2, j >= 0; i++, j--) {
// cnt += num[i][j] ^ 1;
if (num[i][j] == !flag) {
cnt++;
ans.pb(make_pair(i, j));
}
}
if (cnt <= 2) {
printf("%d\n", cnt);
_for(i, 0, cnt) {
printf("%d %d\n", ans[i].first + 1, ans[i].second + 1);
}
return true;
} else return false;
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int t, n, a, b;
int k = 1;
scanf("%d", &t);
while (t--) {
scanf("%d", &n); getchar();
_for(i, 0, n) {
_for(j, 0, n) {
num[i][j] = getchar() - '0';
}
getchar();
}
bool flag = false;
flag = solve(1);
if (!flag) flag = solve(0);
if (!flag) printf("0\n");
}
return 0;
}