题目大意:
一个
n∗n
的
01
矩阵,将数字
1
分成两部分,使得其中一部分通过翻转
分析:
刚开始看不懂题意,还以为翻转平移可以随便做,纠结了半天。。。
将每一个
1
的格子编号,枚举操作方案,如果某个
很明显如果有奇环或奇链无解。
时间复杂度
O(n4)
。
AC code:
#include <cstdio>
#include <cstring>
#include <iostream>
#define mp make_pair
#define ONLINE_JUDGE
const int MAXN = 29;
int n;
int g[MAXN][MAXN];
int tot1;
int to[MAXN*MAXN], fr[MAXN*MAXN];
int ans[MAXN][MAXN];
bool vis[MAXN*MAXN];
std::pair<int,int> Map[MAXN*MAXN];
bool inside(int x) {return x >= 1 && x <= n;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu229.in", "r", stdin);
freopen("sgu229.out", "w", stdout);
#endif
std::ios::sync_with_stdio(0);
std::cin >> n;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
{
char c;
std::cin >> c;
g[i][j] = c-'0';
if(g[i][j])
{
g[i][j] = ++tot1;
Map[tot1] = std::mp(i, j);
}
}
if(tot1&1)
{
std::cout << "NO" << std::endl;
return 0;
}
for(int p = 0; p <= 3; ++p)
for(int addx = -n; addx <= n; ++addx)
for(int addy = -n; addy <= n; ++addy)
{
memset(to, 0, sizeof(to));
memset(fr, 0, sizeof(fr));
memset(ans, 0, sizeof(ans));
memset(vis, false, sizeof(vis));
for(int x = 1; x <= n; ++x)
for(int y = 1; y <= n; ++y)
if(g[x][y])
{
int nx, ny;
if(p == 0) nx = x, ny = y;
else if(p == 1) nx = y, ny = n-x+1;
else if(p == 2) nx = n-x+1, ny = n-y+1;
else nx = n-y+1, ny = x;
nx += addx, ny += addy;
if(inside(nx) && inside(ny) && g[nx][ny])
{
if(x == nx && y == ny) goto next_option;
int p = g[x][y], q = g[nx][ny];
fr[q] = p, to[p] = q;
}
}
for(int i = 1; i <= tot1; ++i)
if(!vis[i] && !fr[i] && to[i])
{
int cnt = 0, j = i;
while(j)
{
if(!(cnt&1)) ans[Map[j].first][Map[j].second] = 1;
vis[j] = true;
j = to[j], ++cnt;
}
if(cnt&1) goto next_option;
}
for(int i = 1; i <= tot1; ++i)
if(!vis[i])
{
int cnt = 0, j = i;
while(!vis[j] && j)
{
if(!(cnt&1)) ans[Map[j].first][Map[j].second] = 1;
vis[j] = true;
j = to[j], ++cnt;
}
if(cnt&1) goto next_option;
}
std::cout << "YES" << std::endl;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
std::cout << ans[i][j];
std::cout << std::endl;
}
return 0;
next_option:;
}
std::cout << "NO" << std::endl;
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}