http://poj.org/problem?id=2965
16个位置分别有两个状态,用一个16位的二进制表示,对beg按位或运算得到初始状态,bfs中,用只包含0,1的16进制数实现翻转操作。
剩下的就是单纯的bfs了。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std ;
int dir[16]={0x111f, 0x222f, 0x444f, 0x888f,
0x11f1, 0x22f2, 0x44f4, 0x88f8,
0x1f11, 0x2f22, 0x4f44, 0x8f88,
0xf111, 0xf222, 0xf444, 0xf888 } ;
bool vis[1<<17] ;
int beg ;
struct data{
int pre, step, value, x, y ;
}q[1<<17] ;
void bfs(){
int head, end ;
data temp, t ;
head = end = 0 ;
temp.value = beg ;
temp.step = 0 ;
q[head] = temp ;
end = 1 ;
vis[beg] = 1 ;
while(end>head){
temp = q[head++] ;
for(int i=0; i<16; i++){
t = temp ;
t.value ^= dir[i] ;
if(!vis[t.value]){
vis[t.value] = 1 ;
t.step = q[head-1].step + 1 ;
t.pre = head - 1 ;
t.x = i / 4 + 1 ;
t.y = i % 4 + 1 ;
if(t.value==0){
printf("%d\n", t.step) ;
while(t.step){
printf("%d %d\n", t.x, t.y) ;
t = q[t.pre] ;
}
return ;
}
q[end++] = t ;
}
}
}
}
int main(){
int i, j ;
char a ;
beg = 0 ;
for(i=0; i<16; i++){
cin >> a ;
if(a=='+') beg |= 1<<i ;
}
memset(vis, 0, sizeof(vis)) ;
bfs() ;
return 0 ;}
#include<cstdio>
#include<cstring>
using namespace std ;
int dir[16]={0x111f, 0x222f, 0x444f, 0x888f,
0x11f1, 0x22f2, 0x44f4, 0x88f8,
0x1f11, 0x2f22, 0x4f44, 0x8f88,
0xf111, 0xf222, 0xf444, 0xf888 } ;
bool vis[1<<17] ;
int beg ;
struct data{
int pre, step, value, x, y ;
}q[1<<17] ;
void bfs(){
int head, end ;
data temp, t ;
head = end = 0 ;
temp.value = beg ;
temp.step = 0 ;
q[head] = temp ;
end = 1 ;
vis[beg] = 1 ;
while(end>head){
temp = q[head++] ;
for(int i=0; i<16; i++){
t = temp ;
t.value ^= dir[i] ;
if(!vis[t.value]){
vis[t.value] = 1 ;
t.step = q[head-1].step + 1 ;
t.pre = head - 1 ;
t.x = i / 4 + 1 ;
t.y = i % 4 + 1 ;
if(t.value==0){
printf("%d\n", t.step) ;
while(t.step){
printf("%d %d\n", t.x, t.y) ;
t = q[t.pre] ;
}
return ;
}
q[end++] = t ;
}
}
}
}
int main(){
int i, j ;
char a ;
beg = 0 ;
for(i=0; i<16; i++){
cin >> a ;
if(a=='+') beg |= 1<<i ;
}
memset(vis, 0, sizeof(vis)) ;
bfs() ;
return 0 ;}