/* * Find two paths of length W+H-2 from top-left to * bottom right corner. Use dynamic programming to compute * best[d][r1][r2] = opt value after d steps if paths are now * in rows r1 and r2 where r1 <= r2. * * Answer is in best[W+H-2][H][H] * * Somewhat slow. Maybe due to large inputs? */ import java.io.*; import java.util.*; class tourist_mg { static BufferedReader stdin; static PrintWriter stdout; static final int infty = 1<<30; public static void main(String[] ss) throws Exception { Reader r = new InputStreamReader(System.in); stdin = new BufferedReader(r); Writer w = new OutputStreamWriter(System.out); w = new BufferedWriter(w); stdout = new PrintWriter(w); (new tourist_mg()).run(); stdout.close(); } void run() throws Exception { int n = Integer.parseInt(stdin.readLine()); for (int i = 1; i <= n; ++i) { try { solve(); } catch(Exception e) { System.err.println("Case " + i); } } } void solve() throws Exception { StringTokenizer st = new StringTokenizer(stdin.readLine()); int W = Integer.parseInt(st.nextToken()); int H = Integer.parseInt(st.nextToken()); int D = H+W-2; int[][] val = new int[H+1][W+1]; int[][][] best = new int[D+1][H+1][H+1]; // 0:th row and column are unreachable (probably unneccessary) for(int r = 0; r <= H; ++r) val[r][0] = -infty; for(int c = 1; c <= W; ++c) val[0][c] = -infty; // assume all positions are unreachable for the two paths // Can be speeded up. Only need to fill it in where rows = 0, // where corresponding columns are 0, and where r2 = r1-1 for (int d = 0; d <= D; ++d) for(int r1 = 0; r1 <= H; ++r1) for(int r2 = 0; r2 <= H; ++r2) best[d][r1][r2] = -infty; // Read input and record in val // I wonder if skipping val and saving strings is much slower? for (int r = 1; r <= H; ++r) { String s = stdin.readLine(); int n = s.length(); if (n != W) System.err.println("Line length wrong"); for (int i = 0; i < W; ++i) switch (s.charAt(i)) { case '.' : val[r][i+1] = 0; break; case '*' : val[r][i+1] = 1; break; case '#' : val[r][i+1] = -infty; break; default : System.err.println("Illegal char"); } } // Can clearly reach first square best[0][1][1] = val[1][1]; // Now fill table using dyn. prog. for (int d = 1; d <= D; ++d) { for (int r1 = 1; r1 <= H; ++r1) { int c1 = d-r1+2; if (c1 <= 0) break; if (c1 > W) continue; if (val[r1][c1] != -infty) { best[d][r1][r1] = Math.max( Math.max(best[d-1][r1][r1], best[d-1][r1-1][r1]), best[d-1][r1-1][r1-1] ) + val[r1][c1]; for (int r2 = r1+1; r2 <= H; ++r2) { int c2 = d-r2+2; if (c2 <= 0) break; if (c2 > W) continue; if (val[r2][c2] != -infty) { best[d][r1][r2] = Math.max( Math.max(best[d-1][r1][r2], best[d-1][r1-1][r2]), Math.max(best[d-1][r1][r2-1], best[d-1][r1-1][r2-1]) ); if (best[d][r1][r2] != -infty) { best[d][r1][r2] += val[r1][c1]+val[r2][c2]; } } } } } } stdout.println(best[D][H][H]); } }