// Arup Guha
// 5/10/2019
// Solution to 2019 FHSPS Playoff Problem: Parallel Movement

import java.util.*;

public class parallel_ff {
	
	public static int n;
	public static char[][] board;
	
	// Lots of movement in this problem...
	final public static int[] ALLDX = {-1,-1,-1,0,0,1,1,1};
	final public static int[] ALLDY = {-1,0,1,-1,1,-1,0,1};
	
	final public static int[] ROOKDX = {-1,0,0,1};
	final public static int[] ROOKDY = {0,-1,1,0};
	
	final public static int[] BISHOPDX = {-1,-1,1,1};
	final public static int[] BISHOPDY = {-1,1,-1,1};	
	
	final public static int[] KNIGHTDX = {-2,-2,-1,-1,1,1,2,2};
	final public static int[] KNIGHTDY = {-1,1,-2,2,-2,2,-1,1};	
	

	public static void main(String[] args) {
		
		Scanner stdin = new Scanner(System.in);
		int numCases = stdin.nextInt();
		
		// Process each case.
		for (int loop=0; loop<numCases; loop++) {
			
			n = stdin.nextInt();
			board = new char[n][];
			for (int i=0; i<n; i++)
				board[i] = stdin.next().toCharArray();
			
			// Here is my flow graph.
			FordFulkerson flowgraph = new FordFulkerson(n*n);
			
			int open = 0;
			
			// First, let's just place edges from source to pieces and blanks to sink.
			for (int i=0; i<n; i++) {
				for (int j=0; j<n; j++) {	
					if (board[i][j] == '.') flowgraph.add(n*i+j, n*n+1, 1);
					else					flowgraph.add(n*n, n*i+j, 1);
				}
			}
			
			// Now, we want to add edges from pieces to blanks.
			for (int i=0; i<n; i++) {
				for (int j=0; j<n; j++) {
					if (board[i][j] == '.') continue;
					
					// Get the list and add the ones that go to blank.
					ArrayList<Integer> next = getNext(i, j, board[i][j]);
					for (Integer x: next) 
						if (board[x/n][x%n] == '.')
							flowgraph.add(n*i+j, x, 1);
				}
			}
			
			// Ta da!
			System.out.println(flowgraph.ff());
		}
	}
	
	// Returns all the places you can go from (r,c) with piece that are inbounds.
	public static ArrayList<Integer> getNext(int r, int c, char piece) {
		
		// Store result here.
		ArrayList<Integer> list = new ArrayList<Integer>();
		
		// These pieces can only go "one hop" of their DX/DY array.
		if (piece == 'K' || piece == 'N') {
			
			// Set dx, dy arrays.
			int[] dx = KNIGHTDX;
			int[] dy = KNIGHTDY;
			if (piece == 'K') { dx = ALLDX; dy = ALLDY; }
			
			for (int i=0; i<dx.length; i++) {
				int nr = r + dx[i];
				int nc = c + dy[i];
				if (inbounds(nr,nc)) list.add(nr*n+nc);
			}
		}
		
		// The rest of the pieces can go as many hops as they want.
		else {
			
			// Set up dx, dy arrays.
			int[] dx = ALLDX;
			int[] dy = ALLDY;
			if (piece == 'R') { dx = ROOKDX; dy = ROOKDY; }
			if (piece == 'B') { dx = BISHOPDX; dy = BISHOPDY; }
			
			// Go in all directions.
			for (int i=0; i<dx.length; i++) {
				
				// Try all distances.
				for (int dist = 1; dist<n; dist++) {
					int nr = r + dist*dx[i];
					int nc = c + dist*dy[i];
					if (inbounds(nr,nc)) list.add(nr*n+nc);
				}
			}			
		}
		
		return list;
	}
	
	public static boolean inbounds(int r, int c) {
		return r >= 0 && r < n && c >= 0 && c < n;
	}
}

/*** UCF Team Hackpack Code for Ford-Fulkerson ***/
class FordFulkerson {

	// Stores graph.
	public int[][] cap;
	public int n;
	public int source;
	public int sink;

	// "Infinite" flow.
	final public static int oo = (int)(1E9);

	// Set up default flow network with size+2 vertices, size is source, size+1 is sink.
	public FordFulkerson(int size) {
		n = size + 2;
		source = n - 2;
		sink = n - 1;
		cap = new int[n][n];
	}

	// Adds an edge from v1 -> v2 with capacity c.
	public void add(int v1, int v2, int c) {
		cap[v1][v2] = c;
	}

	// Wrapper function for Ford-Fulkerson Algorithm
	public int ff() {

		// Set visited array and flow.
		boolean[] visited = new boolean[n];
		int flow = 0;

		// Loop until no augmenting paths found.
		while (true) {

			// Run one DFS.
			Arrays.fill(visited, false);
			int res = dfs(source, visited, oo);

			// Nothing found, get out.
			if (res == 0) break;

			// Add this flow.
			flow += res;
		}

		// Return it.
		return flow;
	}

	// DFS to find augmenting math from v with maxflow at most min.
	public int dfs(int v, boolean[] visited, int min) {

		// got to the sink, this is our flow.
		if (v == sink)  return min;

		// We've been here before - no flow.
		if (visited[v])  return 0;

		// Mark this node and recurse.
		visited[v] = true;
		int flow = 0;

		// Just loop through all possible next nodes.
		for (int i = 0; i < n; i++) {

			// We can augment in this direction.
			if (cap[v][i] > 0)
				flow = dfs(i, visited, Math.min(cap[v][i], min));

			// We got positive flow on this recursive route, return it.
			if (flow > 0) {

				// Subtract it going forward.
				cap[v][i] -= flow;

				// Add it going backwards, so that later, we can flow back through this edge as a backedge.
				cap[i][v] += flow;

				// Return this flow.
				return flow;
			}
		}

		// If we get here there was no flow.
		return 0;
	}
}