I think the easiest way to solve this is to model the grid as a graphic. Create a face between two neighbors, also create one edge between two nodes of the same type. After that, a simple BFS from source to dest can respond to the shortest path between two nodes.
http://en.wikipedia.org/wiki/Breadth-first_search
Difficulty - O (V + E). V is the number of nodes, 100x100 and E is the number of edges
People here mention Dijkstra. This solves, but it is necessary, because all the edges stand alone. Dijkstra is a special case of the A-star algorithm, so A * is too much for this problem.
Keep it simple, BFS!
This time is O (R * C) and O (R * C):
import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Scanner; public class DanceBattle { static final int INF = (int)(Integer.MAX_VALUE * 0.5); public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); for(int i = 0; i < N ; ++i) { int R = in.nextInt(); int C = in.nextInt(); int V = R*C; int node = 0, start = 0, end = 0; int nodeColor[] = new int[V]; List<Integer>[] colorMap = new List[10]; for(int color=0;color<10;++color) colorMap[color] = new LinkedList<Integer>(); for(int r = 0; r < R; ++r) { String row = in.next(); for(int c = 0; c<row.length(); ++c) { char v = row.charAt(c); if(v == 'S' ) start = node; else if (v == 'E') end = node; else if (v == 'W') nodeColor[node] = -1; else { int color = (int)(v - '0'); nodeColor[node] = color; colorMap[color].add(node); } node++; } } int neighborhood4[][] = new int[V][4]; for(int j =0 ; j< V; ++j) { int c = j % C; int r = (j - c)/C; int grad = 0; if(neighbors(r,c,r,c+1, R, C)) neighborhood4[j][grad++] = (r) * C + (c+1); if(neighbors(r,c,r,c-1, R, C)) neighborhood4[j][grad++] = (r) * C + (c-1); if(neighbors(r,c,r+1,c, R, C)) neighborhood4[j][grad++] = (r+1) * C + (c); if(neighbors(r,c,r-1,c, R, C)) neighborhood4[j][grad++] = (r-1) * C + (c); if(grad < 4) neighborhood4[j][grad] = -1; } //bfs int qbegin, qend; int[] Q = new int[V]; int[] dist = new int[V]; for(int j=0; j<V; j++) dist[j] = INF; dist[start] = 0; qbegin = qend = 0; Q[qend++] = start; int complexity = 0; while(qbegin != qend) { int currNode = Q[qbegin++]; for(int j=0; j<4; j++) { int neighbor = neighborhood4[currNode][j]; if(neighbor == -1) break; int color = nodeColor[neighbor]; if(dist[neighbor] == INF && color != -1 ) { Q[qend++] = neighbor; dist[neighbor] = dist[currNode] + 1; } complexity++; } int color = nodeColor[currNode]; if (color == 0) continue; Iterator<Integer> iter = colorMap[color].iterator(); while(iter.hasNext()) { int viz = iter.next(); if(dist[viz] == INF) { Q[qend++] = viz; dist[viz] = dist[currNode] + 1; } iter.remove(); complexity++; } } System.out.printf("%d\n",dist[end]); //System.out.printf("(compl. %d V=%d constant: %.2f)\n", complexity, V, ((float)complexity) / V); } } private static boolean neighbors(int ar, int ac, int br, int bc, int R, int C) { if(ar < 0 || ac < 0 || br < 0 || bc < 0) return false; if(ar >= R || ac >= C || br >= R || bc >= C) return false; return (Math.abs(ar - br) <= 1 && Math.abs(ac - bc) ==0) || (Math.abs(ar - br) == 0 && Math.abs(ac - bc) <=1); } }