http://poj.org/problem?id=1753
算法要点:
对于每个格子,它要么反转0次,要么反转1次(当然,它的邻格子也跟着反转),因为它反转偶数次和反转0次的效果是一样的,同理反转奇数次的效果和反转1次的效果是一样的。
2.由于只有16个格子,我们可以选择0个格子,1个格子,2个格子,3个格子……进行反转,总的选择情况为c(16,0),C(16,1)….C(16,16)
3.当0个格子被反转时,看它是否为纯色,否则选择一个格子进行反转(有16种选择),看反转后是否为纯色,否则选择两个格子进行反转(有120种选择),看反转后是否为纯色……
4.只要”3过程”中有纯色出现,就停止”3过程”,输出相应的被选择的格子个数,结束。如果16个格子都被翻转了,还是没变成纯色,则输出“Impossible”。
#include <stdio.h>
#include <stdlib.h>
//#define TEST
#define SIZE 4
#define BASE SIZE*SIZE
#define B 'b'
#define W 'w'
typedef enum{
FALSE,
TRUE,
}bool_T;
bool_T m[BASE];
bool_T s[BASE];
bool_T f[BASE];
//检查是否纯色
bool_T checkfinal(bool_T *maze){
for(int i=0;i<BASE-1;i++){
if(maze[i]!=maze[i+1])
return FALSE;
}
return TRUE;
}
//一个组合,进行flig
bool_T check(){
int x,y;
for(int i=0;i<BASE;i++){
s[i]=m[i];
}
for(int i=0;i<BASE;i++){//检查那些cell需要flip
if(f[i]){
int new_loc;
x=i/SIZE;
y=i%SIZE;
s[i]=s[i]?FALSE:TRUE;
//up
if(x>0){
new_loc = (x-1)*SIZE+y;
s[new_loc]=s[new_loc]?FALSE:TRUE;
}
//down
if((x+1)<SIZE){
new_loc = (x+1)*SIZE+y;
s[new_loc]=s[new_loc]?FALSE:TRUE;
}
//left
if(y>0){
new_loc = x*SIZE+y-1;
s[new_loc]=s[new_loc]?FALSE:TRUE;
}
//right
if((y+1)<SIZE){
new_loc = x*SIZE+y+1;
s[new_loc]=s[new_loc]?FALSE:TRUE;
}
}
}//for
return checkfinal(s);
/*
for(int i=0;i<BASE;i++){
if(f[i])
printf("%d ",i);
else
printf(" ",i);
}
printf("\n");
*/
}
//flip num个格子,如果变成纯色,返回true,否则返回false
bool_T flip(int start, int num){
if(num == (BASE-start)){
for(int i=start;i<BASE;i++)
f[i]=TRUE;
//一个组合
return check();
}
else if(num==0){
for(int i=start;i<BASE;i++){
f[i]=FALSE;
}
//一个组合
return check();
}else{
f[start]=FALSE;
if(!flip(start+1,num)){
f[start]=TRUE;
return flip(start+1,num-1);
}else{
return TRUE;
}
}
return FALSE;
}
void printM(bool_T *m){
#if defined(TEST)
int x,y;
for(int i=0;i<BASE;i++){
x=i/SIZE;
y=i%SIZE;
if(m[i])
printf("b");
else
printf("w");
if((SIZE-1)==y)
printf("\n");
}
#endif
}
int main()
{
int i,j;
int flag;
char array[100]={"bbbbbbbbbbbwbbww"};//{"bbwwbbbwbbbbbbbb"};
#if !defined(TEST)
while(EOF!=scanf("%s",array)){
flag=FALSE;
for(i=1;i<SIZE;i++){
scanf("%s",array+i*SIZE);
}
#endif
for(i=0;i<BASE;i++){
if('b'==array[i])
m[i]=TRUE;
else
m[i]=FALSE;
}
printM(m);
for(i=0;i<=BASE;i++){
int result=flip(0,i);
if(flag=result){
printf("%d\n",i);
break;
}
}
if(!flag)
printf("Impossible\n");
#if !defined(TEST)
}
#endif
return 0;
}