Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which is colored black on one side and white on the other side.
As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.
Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".
Lines 2.. M+1: Line i+1 describes the colors (left to right) of row i of the grid with N space-separated integers which are 1 for black and 0 for white
4 4 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1Sample Output
0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0
另外,对于第一行的枚举,可以从0到(1<<n)-1枚举i,然后对此i(视为二进制)的各位数字(为0或1)进行分别提取放进翻转方案的第一行,就可以得到所有的第一行可能翻转方案。需要对位运算知识稍有了解。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int dx[5]={1,-1,0,0,0};
const int dy[5]={0,0,0,1,-1};
int m,n,ans=-1;
int tile[16][16],flip[16][16],final[16][16];
//tile为初始黑白瓷砖,flip[i][j]=1时为翻转这块瓷砖,final是最终输出
int get(int x,int y){//判断这块砖被翻转之后是黑是白
int c=tile[x][y];//本身的原始色
for(int i=0;i<5;i++){
int tx=x+dx[i],ty=y+dy[i];
//只有它周围的五个砖(包括自己)在翻转时才会影响到它的颜色变化
if(tx>=0 && tx<m && ty>=0 && ty<n)
c+=flip[tx][ty];
}
return c%2;
}
int cal(){
for(int i=1;i<m;i++)//第一行预设好了,所以从第二行开始
for(int j=0;j<n;j++){
if(get(i-1,j)!=0)//如果上面那个是黑砖,需要翻转下面这块砖来导致上面翻成白色
flip[i][j]=1;
}
for(int i=0;i<n;i++){
if(get(m-1,i)!=0)//最后一行还需要翻转的话就无解了
return -1;
}
int res=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
res+=flip[i][j];//共翻转了几次
return res;
}
int main(){
//输入
cin>>m>>n;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
cin>>tile[i][j];//1是黑色,0是白色
for(int i=0;i<1<<n;i++){//枚举第一行的所有状态
memset(flip,0,sizeof(flip));//每换一种新情况都要重新写flip
for(int j=0;j<n;j++){
flip[0][n-1-j]=i>>j&1;//先移位再与1
}
int num=cal();
if(num>=0 && (ans<0||num<ans) ){//记录最优解
ans=num;
memcpy(final,flip,sizeof(flip));
}
}
//输出
if(ans==-1)
cout<<"IMPOSSIBLE"<<endl;
else
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
printf("%d%c",final[i][j],j==n-1?'\n':' ');
return 0;
}