// BAPC06 Evacuation, Marijn Kruisselbrink
import java.util.*;
class Point {
	int x, y;
	Point(int x, int y) { this.x = x; this.y = y; }
	public boolean equals(Object o) { Point p = (Point) o; return p.x == x && p.y == y; }
	public int hashCode() { return x ^ y; }
}
       class Main {
	static Scanner sc = new Scanner(System.in);
	public static void main(String[] a) {
		int n = sc.nextInt(); while (n-->0) new Main().solve();
	}

	char[][] map = new char[12][12];
	List<Point> doors = new ArrayList<Point>();
	List<Point> dots = new ArrayList<Point>();
	int w, h;
	int[][][] dist = new int[50][12][12];
	void solve() {
		h = sc.nextInt();
		w = sc.nextInt();
		for (int y = 0; y < h; y++) {
			String s = sc.next();
			for (int x = 0; x < w; x++) {
				map[x][y] = s.charAt(x);
				if (map[x][y] == 'D') doors.add(new Point(x, y));
				if (map[x][y] == '.') dots.add(new Point(x, y));
			}
		}
		for (int i = 0; i < doors.size(); i++) {
			Point p = doors.get(i);
			fill(i, p.x, p.y, 0);
		}
		int max = 0;
		for (Point p: dots) if (map[p.x][p.y] == '.') {
			boolean b = false;
			int min = Integer.MAX_VALUE;
			for (int i = 0; i < doors.size(); i++) if (dist[i][p.x][p.y] != 0) {
				min = Math.min(min, dist[i][p.x][p.y]);
				b = true;
			}
			if (!b) {
				printf("impossible\n");
				return;
			}
			max = Math.max(max, min);
		}
		if (dots.size() == 0) {
			printf("0\n"); return;
		}
		int a = Math.max(max, dots.size() / doors.size())-1, b = dots.size()+1;
		while (a != b-1) {
//			printf("%d - %d\n", a, b);
			int h = (a+b)/2;
			if (match(h)) {
				b = h;
			} else {
				a = h;
			}
		}
		printf("%d\n", b);
	}

	void fill(int door, int x, int y, int d) {
		if (x < 0 || x >= w || y < 0 || y >= h) return;
		if (dist[door][x][y] != 0 && dist[door][x][y] <= d) return;
		if (d != 0 && map[x][y] != '.') return;
		dist[door][x][y] = d++;
		fill(door, x-1, y, d);
		fill(door, x+1, y, d);
		fill(door, x, y-1, d);
		fill(door, x, y+1, d);
	}

	boolean[] visited = new boolean[101*50];
	Point[] match = new Point[101*50];
	boolean match(int max) {
//		printf("call match(%d)\n", max);
		Arrays.fill(match, null);
		for (Point p: dots) {
			Arrays.fill(visited, false);
			boolean b = false;
foo:			for (int d = 0; d < doors.size(); d++) {
//				printf("door: %d/%d\n", d, doors.size());
				for (int z = 1; z <= max; z++) {
					if (dist[d][p.x][p.y] <= z && dist[d][p.x][p.y] > 0) {
						if (recurse(d, z, max)) {
							match[z*50+d] = p;
						//	printf("match[%d, %d] = (%d, %d)\n", z, d, p.x, p.y);
							b = true;
							break foo;
						}// else return false;
					}
				}
			}
			if (!b) return false;
		}
		return true;
	}
	
	boolean recurse(int d, int z, int max) {
//		printf("   recurse(%d, %d, %d)\n", d, z, max);
		int b = z*50+d;
		if (visited[b]) return false;
		visited[b] = true;
		if (match[b] != null) {
			Point p = match[b];
			for (int D = 0; D < doors.size(); D++) {
				for (int Z = 1; Z <= max; Z++) {
					int B = Z*50+D;
					if (B != b && dist[D][p.x][p.y] <= Z && dist[D][p.x][p.y] > 0) {
						if (recurse(D, Z, max)) {
							match[b] = null;
							match[B] = p;
//							printf("match[%d, %d] = (%d, %d)\n", Z, D, p.x, p.y);
							return true;
						}
					}
				}
			}
			return false;
		} else return true;
	}
	
	void printf(String s, Object... o) {
		System.out.printf(s, o);
	}
}

