http://poj.org/problem?id=2965枚举。刚开始拿到就bfs,结果第一组数据就跑了好几秒!16^16啊,吃不消的。原来每个位置肯定最多就只翻动一次嘛,根据这个可枚举了,翻或者不翻,0,1嘛。2^16,能搞定了。
我还是喜欢用一维数组来表示棋盘状态,i-->1到16分别对应格子((i-1)/4+1,(i-1)A%4+1),a[i]里,0表示关1表示开,t[i]里0表示不翻转1表示翻转。OK,16重循环枚举吧,应该是写过最多的循环了吧。嘿嘿:
#include<stdio.h>
int a[17],b[17],t[17];
int check()
{
int i,sum=0;
for (i=1;i<=16;i++)
sum+=b[i];
if (sum==16)
return 1;
return 0;
}
int turn(int s)
{
int i,x,y;
x=(s-1)/4+1;y=(s-1)%4+1;
for (i=1;i<=4;i++)
{
b[x*4-4+i]=1-b[x*4-4+i];
b[y]=1-b[y];
y=y+4;
}
b[s]=1-b[s];
}
int main()
{
int i,j,step;
char ch;
for (i=1;i<=4;i++)
{
for (j=1;j<=4;j++)
{
scanf("%c",&ch);
if (ch=='-')
a[i*4-4+j]=1;
else
a[i*4-4+j]=0;
}
scanf("%c",&ch);
}
for (t[1]=0;t[1]<=1;t[1]++)
for (t[2]=0;t[2]<=1;t[2]++)
for (t[3]=0;t[3]<=1;t[3]++)
for (t[4]=0;t[4]<=1;t[4]++)
for (t[5]=0;t[5]<=1;t[5]++)
for (t[6]=0;t[6]<=1;t[6]++)
for (t[7]=0;t[7]<=1;t[7]++)
for (t[8]=0;t[8]<=1;t[8]++)
for (t[9]=0;t[9]<=1;t[9]++)
for (t[10]=0;t[10]<=1;t[10]++)
for (t[11]=0;t[11]<=1;t[11]++)
for (t[12]=0;t[12]<=1;t[12]++)
for (t[13]=0;t[13]<=1;t[13]++)
for (t[14]=0;t[14]<=1;t[14]++)
for (t[15]=0;t[15]<=1;t[15]++)
for (t[16]=0;t[16]<=1;t[16]++)
{
for (i=1;i<=16;i++)
b[i]=a[i];
for (i=1;i<=16;i++)
if (t[i])
turn(i);
if (check())
{
step=0;
for (i=1;i<=16;i++)
if (t[i])
step++;
printf("%d\n",step);
for (i=1;i<=16;i++)
if (t[i])
printf("%d %d\n",(i-1)/4+1,(i-1)%4+1);
return 0;
}
}
}
那个行和列都要翻转,则那个要翻转两次,所以别忘了最后还要翻转啊!
不过,还有数学方程来解的,我得看看去。。。。