翻转问题一般是从前面开始贪心,如果是一维的话直接从前面往后贪心,如果是二维的话,就得枚举第一行的状态,然后从第一行往下贪心。
这个题就是二维的开关问题,需要枚举第一行的状态,复杂度为2^n,然后往后遍历贪心。总复杂度为2^n * n*m,因为n < 15 && m < 15,所以能在时限内通过。
PS :要特判n == 1,把他当作一维的来做
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 10 + 10;
#define INF 0x3f3f3f3f
int n,m;
int a[maxn][maxn];
int b[maxn][maxn];
void work(int x,int y)
{
a[x][y] ^= 1;
a[x - 1][y] ^= 1;
a[x + 1][y] ^= 1;
a[x][y - 1] ^= 1;
a[x][y + 1] ^= 1;
}
int vis[maxn][maxn];
int main()
{
while( ~ scanf("%d%d",&n,&m))
{
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
scanf("%d",&b[i][j]);
if(n == 1 && m == 1)
{
if(b[1][1] == 1)
puts("1");
else puts("0");
continue;
}
if(n == 1)
{
int ans = 0;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
a[i][j] = b[i][j];
for(int j = 1; j < m; j ++)
{
if(a[1][j] == 1)
{
work(1,j + 1);
ans ++;
vis[1][j + 1] = 1;
}
}
// cout << ans << endl;
bool flags = 1;
for(int j = 1; j <= m; j ++)
if(a[1][j] == 1)
{
flags = 0;
// cout << j << endl;
puts("IMPOSSIBLE");
break;
}
if(flags)
for(int j = 1; j <= m; j ++)
printf("%d%c",vis[1][j],j <= m - 1 ? ' ' : '\n');
continue;
}
int ans = INF;
int temp;
for(int k = 0; k < (1 << n); k ++)//枚举第一层的翻转顺序
{
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
a[i][j] = b[i][j];
int cnt = 0;
memset(vis,0,sizeof(vis));
int temps = 0;
for(int j = 1; j <= n; j ++)
{
if((1 << (j - 1)) & k)
{
work(1,j),vis[1][j] = 1,cnt ++;
}
}
for(int i = 1; i < n; i ++)
{
for(int j = 1; j <= m; j ++)
{
if(a[i][j] == 1)
{
work(i + 1,j);
cnt ++;
vis[i + 1][j] = 1;
}
}
}
for(int j = 1; j <= m; j ++)
if(a[n][j] == 1)
{
cnt = INF;
break;
}
// cout << cnt << " ";
if(cnt < ans)
ans = cnt,temp = k;
}
// cout << endl;
if(ans == INF)
{
puts("IMPOSSIBLE");
continue;
}
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
a[i][j] = b[i][j];
memset(vis,0,sizeof(vis));
for(int j = 1; j <= n; j ++)
{
if((1 << (j - 1)) & temp)
work(1,j),vis[1][j] = 1;
}
for(int i = 1; i < n; i ++)
{
for(int j = 1; j <= m; j ++)
{
if(a[i][j] == 1)
{
work(i + 1,j);
vis[i + 1][j] = 1;
}
}
}
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++)
{
printf("%d%c",vis[i][j],j < m ? ' ' : '\n');
}
}
}
return 0;
}