M代表横坐标,N代表纵坐标,res是最终的反转情况,tem是中间过程记录的某一种反转情况
init是初始输入的数据。
#include<stdio.h>
#define MAX_N 16
int init[MAX_N][MAX_N],res[MAX_N][MAX_N],tem[MAX_N][MAX_N];
int M,N;
int mov[][2]={0,0,0,1,0,-1,1,0,-1,0};
int color(int x,int y)//判断格子x,y现在的颜色,1代表黑色,代表白色
{
int x1,y1,num,i;
num=init[x][y];//首先是输入的颜色
for(i=0;i<5;i++)
{
x1=x+mov[i][0];
y1=y+mov[i][1];
if(x1>=0&&x1<M&&y1>=0&&y1<N)
num+=tem[x1][y1];//再加上 上下左右旁边格子是否翻动的情况
}
return num%2;//如果是偶数,则相当于格子是白色,否则就是黑色。
}
int calc(void)
{
int i,j,sum;
for(i=1;i<M;i++)
for(j=0;j<N;j++)
{
if(color(i-1,j))//如果是黑色
tem[i][j]=1;//那么就要反转这个黑色格子(i-1,j)下面的格子(i,j)
}
for(j=0;j<N;j++)//检查最后一行格子是否全是白色
if(color(M-1,j))
return -1;
sum=0;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
sum+=tem[i][j];//计算反转的次数
return sum;
}
int main(void)
{
int i,j,sum,co;
scanf("%d%d",&M,&N);
for(i=0;i<M;i++)
for(j=0;j<N;j++)
scanf("%d",&init[i][j]);
sum=-1;
for(i=0;i<1<<N;i++)
{
memset(tem,0,sizeof(tem));
for(j=0;j<N;j++)
tem[0][N-j-1]=i>>j&1;
co=calc();
if(co>0&&(sum<0||sum>co))
{
sum=co;
memcpy(res,tem,sizeof(tem));
}
}
if(sum<0)
printf("IMPOSSIBLE\n");
else
{
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
printf("%d ",res[i][j]);
printf("\n");
}
}
}