1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <bitset> 10 11 using namespace std; 12 13 #define print(x) cout<<x<<endl 14 #define input(x) cin>>x 15 #define SIZE 12 16 #define elif else if 17 #define INF 1<<30 18 #define MOD 100000007 19 20 struct point 21 { 22 int x,y; 23 point(){x=y=-1;} 24 point(int i_x,int i_y) 25 { 26 x=i_x;y=i_y; 27 } 28 friend bool operator == (const point& a,const point& b) 29 { 30 return a.x==b.x && a.y==b.y; 31 } 32 33 friend bool operator != (const point& a,const point& b) 34 { 35 return !(a.x==b.x && a.y==b.y); 36 } 37 }; 38 39 char g[SIZE][SIZE]; 40 point piece[SIZE]; 41 int m,n,ind; 42 const int mx[]={0,1,0,-1}; 43 const int my[]={-1,0,1,0}; 44 bitset<MOD> hash; 45 //TLE: 46 //Hash is faster than Set 47 48 49 int makeStatus(const point& pawn,const point& mir,const point& knight,int knightDir,int getMem) 50 { 51 int res=0; 52 res|=getMem; 53 res<<=4;res|=knight.x; 54 res<<=4;res|=knight.y; 55 res<<=2;res|=knightDir; 56 res<<=4;res|=mir.x; 57 res<<=4;res|=mir.y; 58 res<<=4;res|=pawn.x; 59 res<<=4;res|=pawn.y; 60 return res; 61 } 62 63 bool inMap(const point& p) 64 { 65 if(p.x>=0 && p.x<m && p.y>=0 && p.y<n) 66 { 67 if(g[p.y][p.x]=='R') return false; 68 else return true; 69 } 70 return false; 71 } 72 73 struct node 74 { 75 unsigned int status; 76 int step; 77 78 node(){} 79 node(int i_status,int i_step) 80 { 81 status=i_status; 82 step=i_step; 83 } 84 int OK()//Drei Status caused WA 85 { 86 int st=status; 87 int res=status>>26; 88 int a,b; 89 a=b=(1<<4)-1; 90 b&=st;st>>=4; 91 a&=st;st>>=4; 92 point pawn=point(a,b); 93 a=b=(1<<4)-1; 94 b&=st;st>>=4; 95 a&=st;st>>=4; 96 point mirPawn=point(a,b); 97 int ok=(1<<ind)-1; 98 if(ind==0) ok=0; 99 if(g[pawn.y][pawn.x]=='E' && g[mirPawn.y][mirPawn.x]=='E') 100 { 101 if(res==ok) return true; 102 else return -1; 103 } 104 else return false; 105 } 106 bool move(int dir) 107 { 108 step++; 109 int a,b; 110 a=b=(1<<4)-1; 111 b&=status;status>>=4; 112 a&=status;status>>=4; 113 point pawn=point(a,b); 114 115 a=b=(1<<4)-1; 116 b&=status;status>>=4; 117 a&=status;status>>=4; 118 point mirPawn=point(a,b); 119 120 a=(1<<2)-1; 121 a&=status; 122 int knightDir=a; 123 status>>=2; 124 125 a=b=(1<<4)-1; 126 b&=status;status>>=4; 127 a&=status;status>>=4; 128 point knight=point(a,b); 129 130 int gain=status; 131 132 point nextPawn=pawn; 133 nextPawn.x+=mx[dir]; 134 nextPawn.y+=my[dir]; 135 if(inMap(nextPawn)) 136 { 137 if(nextPawn==knight || nextPawn==mirPawn) return false; 138 pawn=nextPawn; 139 } 140 else return false; 141 142 point nextMirPawn=mirPawn; 143 nextMirPawn.x+=mx[(dir+2)%4]; 144 nextMirPawn.y+=my[(dir+2)%4]; 145 if(inMap(nextMirPawn) && nextMirPawn!=knight && nextMirPawn!=pawn) 146 { 147 mirPawn=nextMirPawn; 148 } 149 point nextKnight=knight; 150 nextKnight.x+=mx[knightDir]; 151 nextKnight.y+=my[knightDir]; 152 if(inMap(nextKnight)) knight=nextKnight; 153 else knightDir=(knightDir+2)%4; 154 155 if(g[pawn.y][pawn.x]=='E' && g[mirPawn.y][mirPawn.x]=='E') 156 { 157 status=makeStatus(pawn,mirPawn,knight,knightDir,gain); 158 } 159 else 160 { 161 if(knight==pawn || knight==mirPawn) return false; 162 for(int i=0;i<ind;i++) 163 { 164 if(pawn==piece[i]) gain|=(1<<i);//Only Alice can attach to the Memory Piece WA 165 } 166 status=makeStatus(pawn,mirPawn,knight,knightDir,gain); 167 } 168 return true; 169 } 170 171 void printinfo() 172 { 173 char tg[SIZE][SIZE]; 174 memcpy(tg,g,sizeof(g)); 175 print("INFO:"<<step); 176 int st=status; 177 int a,b; 178 a=b=(1<<4)-1; 179 b&=status;status>>=4; 180 a&=status;status>>=4; 181 point pawn=point(a,b); 182 tg[b][a]='A'; 183 184 a=b=(1<<4)-1; 185 b&=status;status>>=4; 186 a&=status;status>>=4; 187 point mirPawn=point(a,b); 188 tg[b][a]='B'; 189 190 a=(1<<2)-1; 191 a&=status; 192 int knightDir=a; 193 status>>=2; 194 printf("KnightDir:%d\n",knightDir); 195 196 a=b=(1<<4)-1; 197 b&=status;status>>=4; 198 a&=status;status>>=4; 199 point knight=point(a,b); 200 tg[b][a]='K'; 201 int gain=status; 202 printf("Gain:%d\n",gain); 203 status=st; 204 for(int i=0;i<ind;i++) 205 { 206 207 if(!(gain & (1<<i))) 208 { 209 tg[piece[i].y][piece[i].x]='M'; 210 } 211 } 212 for(int i=0;i<n;i++) print(tg[i]); 213 print("-------------------"); 214 } 215 }; 216 217 218 inline int char2Dir(char x) 219 { 220 switch(x) 221 { 222 case 'N':return 0;break; 223 case 'E':return 1;break; 224 case 'S':return 2;break; 225 case 'W':return 3;break; 226 } 227 return -1; 228 } 229 230 231 int bfs(int i_status) 232 { 233 queue<node> q; 234 int ans=INF; 235 hash.reset(); 236 q.push(node(i_status,0)); 237 while(!q.empty()) 238 { 239 node now=q.front(); 240 q.pop(); 241 //now.printinfo(); 242 if(hash[now.status%MOD]) continue; 243 else hash[now.status%MOD]=1; 244 int ok=now.OK(); 245 if(ok==1) 246 { 247 ans=min(ans,now.step); 248 break; 249 } 250 elif(ok==-1) continue; 251 for(int i=0;i<4;i++) 252 { 253 node next=now; 254 if(next.move(i)) q.push(next); 255 } 256 } 257 return ans; 258 } 259 260 int main() 261 { 262 //freopen("input.txt","r",stdin); 263 char cmd[4]; 264 while(input(n>>m)) 265 { 266 for(int i=0;i<n;i++) scanf("%s",g[i]); 267 268 scanf("%s",cmd); 269 ind=0; 270 point pawn,mirPawn; 271 point knight; 272 for(int i=0;i<n;i++) 273 { 274 for(int j=0;j<m;j++) 275 { 276 if(g[i][j]=='A') pawn=point(j,i); 277 elif(g[i][j]=='B') mirPawn=point(j,i); 278 elif(g[i][j]=='K') knight=point(j,i); 279 elif(g[i][j]=='M') piece[ind++]=point(j,i); 280 281 if(g[i][j]!='E' && g[i][j]!='*' && g[i][j]!='R') 282 { 283 g[i][j]='*'; 284 } 285 } 286 } 287 int status=makeStatus(pawn,mirPawn,knight,char2Dir(*cmd),0); 288 int ans=bfs(status); 289 if(ans>=INF) ans=-1; 290 print(ans); 291 } 292 return 0; 293 }