题目链接:http://poj.org/problem?id=2965
题意:4*4的地图,反转某一点的话他所在的行和列均反转,问翻转到全部为-的时候最少几步
思路:有种精妙的解法,没看= =,第一反应就是压缩后进行bfs,不难,但是实现的时候。。是太久没写搜索了么。。标题的含义就是我很水。。。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = (1<<16) + 10;
int fa[maxn];
int t[maxn];
int nn[maxn];
int way[maxn];
int num[20];
int vis[maxn];
int bfs(int s){
int i = 0,now=0;//i当前存到数组那一位,now bfs到那一位
fa[0]=-1;
t[0]=0;
nn[0]=s;
while(1){
if(!nn[now])break;
for(int k = 0;k < 16; k ++){
if(vis[nn[now]^num[k]])continue;
i++;
fa[i]=now;
t[i] = t[now]+1;
nn[i] = nn[now]^num[k];
vis[nn[now]^num[k]]=1;
way[i] = k;
if(nn[i]==0){now = i-1;break;}
}
now++;
}
cout<<t[now]<<endl;
for(int i=now;i;i=fa[i]){
cout<<way[i]/4+1<<' '<<way[i]%4+1<<endl;
}
}
void make(int now){
int a[4][4]={0};
for(int i=0;i<4;i++){
a[i][now%4]=1;
a[now/4][i]=1;
}
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(a[i][j])num[now]+=1<<(4*i+j);
}
void init(){
for(int i=0;i<16;i++){
make(i);
}
}
int main(){
init();
int s=0;
char c;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
scanf("%c",&c);
if(c=='+')s+=1<<(4*i+j);
}
getchar();
}
bfs(s);
return 0;
}