Problem Description
4 6 3 *** *B* *B* *H* *H* *** 4 4 **** *BB* *HH* **** 4 4 **** *BH* *HB* **** 5 6 ****** *.BB** *.H*H* *..*.* ******
3 1 2 Sorry , sir , my poor program fails to get an answer.
const int Max_N = 25 ; const int inf = (1<<30) ; char table[Max_N][Max_N] ; int minstep[Max_N][Max_N][Max_N][Max_N] ; int N , M ; struct Point{ int x ; int y ; int IsOK ; Point(){} Point(int i , int j , int s):x(i) ,y(j) , IsOK(s){} }; struct Node{ Point A ; Point B ; int step ; Node(){} Node(Point a , Point b , int s):A(a) ,B(b),step(s){} }; int d[4][2] = {{1,0} , {0,1} , {-1,0} ,{0 ,-1}} ; int cango(int x , int y){ return 1 <= x && x <= N && 1 <= y && y <= M ; } int bfs(Node s){ int i , j , x , y ; for(i = 1 ; i <= N ; i++) for(j = 1 ; j <= M ; j++) for(x = 1 ; x <= N ; x++) for(y = 1 ; y <= M ; y++) minstep[i][j][x][y] = inf ; minstep[s.A.x][s.A.y][s.B.x][s.B.y] = 0 ; queue<Node> que ; Node now ; Point A , B , nA , nB ; int ax , ay , bx , by ; que.push(s) ; while(! que.empty()){ now = que.front() ; que.pop() ; A = now.A ; B = now.B ; if(A.IsOK && B.IsOK) return now.step ; for(i = 0 ; i < 4 ; i++){ ax = A.x + d[i][0] ; ay = A.y + d[i][1] ; bx = B.x + d[i][0] ; by = B.y + d[i][1] ; if(table[ax][ay] == '*' && table[bx][by] == '*') continue ; if(table[ax][ay] == '*'){ ax = A.x ; ay = A.y ; } if(table[bx][by] == '*'){ bx = B.x ; by = B.y ; } if(!A.IsOK && !B.IsOK && ax == bx && ay == by) continue ; if(A.IsOK){ nA = A ; nB.x = bx ; nB.y = by ; if(table[bx][by] == 'H' && !(A.x==bx&&A.y==by)) nB.IsOK = 1 ; else nB.IsOK = 0 ; if(minstep[nA.x][nA.y][nB.x][nB.y] > now.step + 1){ que.push(Node(nA , nB , now.step+1)) ; minstep[nA.x][nA.y][nB.x][nB.y] = now.step + 1 ; } } else if(B.IsOK){ nB = B ; nA.x = ax ; nA.y = ay ; if(table[ax][ay] == 'H' && !(B.x==ax&&B.y==ay)) nA.IsOK = 1 ; else nA.IsOK = 0 ; if(minstep[nA.x][nA.y][nB.x][nB.y] > now.step+1){ que.push(Node(nA , nB , now.step+1)) ; minstep[nA.x][nA.y][nB.x][nB.y] = now.step + 1 ; } } else{ nA.x = ax ; nA.y = ay ; if(table[ax][ay] == 'H') nA.IsOK = 1 ; else nA.IsOK = 0 ; nB.x = bx ; nB.y = by ; if(table[bx][by] == 'H') nB.IsOK = 1 ; else nB.IsOK = 0 ; if(minstep[nA.x][nA.y][nB.x][nB.y] > now.step + 1){ que.push(Node(nA , nB , now.step+1)) ; minstep[nA.x][nA.y][nB.x][nB.y] = now.step + 1 ; } } } } return -1 ; } int main(){ int T , i , j ; vector<Point> List ; cin>>T ; while(T--){ List.clear() ; scanf("%d%d" ,&N ,&M) ; for(i = 1 ; i <= N ; i++) scanf("%s" , table[i]+1) ; for(i = 1 ; i <= N ; i++){ for(j = 1 ; j <= M ; j++){ if(table[i][j] == 'B') List.push_back(Point(i , j , 0)) ; } } int ans =bfs(Node(List[0] , List[1] , 0)) ; if(ans == -1) puts("Sorry , sir , my poor program fails to get an answer.") ; else printf("%d\n" ,ans) ; } return 0 ; }
4 4 SX.. XX.. .... 1..D 4 4 S.X1 .... ..XX ..XD 0 0
-1 9
typedef long long LL ; const int Max_N = 9 ; struct MM{ LL Key ; LL Exp ; int ExSize ; MM(){} MM(LL a , LL b , int e):Key(a) , Exp(b) , ExSize(e){} friend bool operator < (const MM &A , const MM &B){ if(A.Key != B.Key) return A.Key < B.Key ; if(A.Exp != B.Exp) return A.Exp < B.Exp ; return A.ExSize < B.ExSize ; } friend bool operator == (const MM &A , const MM &B){ return A.Key == B.Key && A.Exp == B.Exp && A.ExSize == B.ExSize ; } }; set< MM > _hash[Max_N][Max_N] ; struct Node{ int x ; int y ; int step ; int ExSize ; LL explodes ; LL key ; Node(){} friend bool operator < (const Node &A , const Node &B){ return A.step > B.step ; } }; char table[Max_N][Max_N] ; int minstep[Max_N][Max_N][1000] ; int N , M ; int d[4][2] = {{1,0} , {-1 ,0} , {0 , 1} , {0 ,-1}} ; int cango(int x , int y){ return 1 <= x && x <= N && 1 <= y && y <= M ; } int bfs(Node s){ int i , j , k , x , y , idx ; Node now , next ; _hash[s.x][s.y].insert(MM(s.key , s.explodes , s.ExSize)) ; priority_queue<Node> que ; que.push(s) ; while(! que.empty()){ now = que.top() ; que.pop() ; // printf("%d %d %d %d\n" , now.x , now.y , now.ExSize ,now.step) ; if(table[now.x][now.y] == 'D') return now.step ; for(i = 0 ; i < 4 ; i++){ next.x = now.x + d[i][0] ; next.y = now.y + d[i][1] ; if(! cango(next.x , next.y)) continue ; idx = (next.x - 1) * M + next.y - 1 ; if(table[next.x][next.y] == 'X'){ next.explodes = now.explodes ; if(((LL)1<<idx) & now.key){ next.key = now.key ; next.step = now.step + 1 ; next.ExSize = now.ExSize ; } else{ if(now.ExSize <= 0) continue ; next.key = now.key | ((LL)1<<idx) ; next.ExSize = now.ExSize - 1 ; next.step = now.step + 2 ; } if(_hash[next.x][next.y].find(MM(next.key, next.explodes , next.ExSize)) == _hash[next.x][next.y].end()){ que.push(next) ; _hash[next.x][next.y].insert(MM(next.key, next.explodes , next.ExSize)) ; } } else if('1' <= table[next.x][next.y] && table[next.x][next.y] <= '9'){ next.key = now.key ; next.step = now.step + 1 ; if(((LL)1<<idx) & now.explodes){ next.explodes = now.explodes ; next.ExSize = now.ExSize ; } else{ next.explodes = now.explodes | ((LL)1<<idx) ; next.ExSize = now.ExSize + table[next.x][next.y] - '0' ; } if(_hash[next.x][next.y].find(MM(next.key, next.explodes , next.ExSize)) == _hash[next.x][next.y].end()){ que.push(next) ; _hash[next.x][next.y].insert(MM(next.key, next.explodes , next.ExSize)) ; } } else{ next.explodes = now.explodes ; next.step = now.step + 1 ; next.key = now.key ; next.ExSize = now.ExSize ; if(_hash[next.x][next.y].find(MM(next.key, next.explodes , next.ExSize)) == _hash[next.x][next.y].end()){ que.push(next) ; _hash[next.x][next.y].insert(MM(next.key, next.explodes , next.ExSize)) ; } } } } return -1 ; } int main(){ int i , j ; Node start ; while(cin>>N>>M){ if(N == 0 && M == 0) break ; for(i = 1 ; i <= N ; i++) scanf("%s" ,table[i]+1) ; for(i = 1 ; i <= N ; i++){ for(j = 1 ; j <= M ; j++){ if(table[i][j] == 'S'){ start.x = i ; start.y = j ; } } } for(i = 1 ; i <= N ; i++) for(j = 1 ; j <= M ; j++) _hash[i][j].clear() ; start.step = 0 ; start.ExSize = 0 ; start.explodes = (LL)0 ; start.key = (LL)0 ; printf("%d\n" , bfs(start)) ; } return 0 ; }