// Arup Guha
// 5/10/2019
// Alternate Solution to 2019 FHSPS Playoff Problem: Parallel Movement

// This uses Dinic's which is faster than Ford-Fulkerson, wasn't necessary to
// get this to run in time.

import java.util.*;

public class parallel_dinic {
	
	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.
			Dinic flowgraph = new Dinic(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, 0);
					else					flowgraph.add(n*n, n*i+j, 1, 0);
				}
			}
			
			// 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, 0);
				}
			}
			
			// Ta da!
			System.out.println(flowgraph.flow());
		}
	}
	
	// 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 Dinitz's Algorithm ***/

class Edge {
	int v1, v2, cap, flow;
	Edge rev;
	Edge(int V1, int V2, int Cap, int Flow) {
		v1 = V1;
		v2 = V2;
		cap = Cap;
		flow = Flow;
	}
}

class Dinic {

	// Queue for the top level BFS.
	public ArrayDeque<Integer> q;

	// Stores the graph.
	public ArrayList<Edge>[] adj;
	public int n;

	// s = source, t = sink
	public int s;
	public int t;


	// For BFS.
	public boolean[] blocked;
	public int[] dist;

	final public static int oo = (int)1E9;

	// Constructor.
	public Dinic (int N) {

		// s is the source, t is the sink, add these as last two nodes.
		n = N; s = n++; t = n++;

		// Everything else is empty.
		blocked = new boolean[n];
		dist = new int[n];
		q = new ArrayDeque<Integer>();
		adj = new ArrayList[n];
		for(int i = 0; i < n; ++i)
			adj[i] = new ArrayList<Edge>();
	}

	// Just adds an edge and ALSO adds it going backwards.
	public void add(int v1, int v2, int cap, int flow) {
		Edge e = new Edge(v1, v2, cap, flow);
		Edge rev = new Edge(v2, v1, 0, 0);
		adj[v1].add(rev.rev = e);
		adj[v2].add(e.rev = rev);
	}

	// Runs other level BFS.
	public boolean bfs() {

		// Set up BFS
		q.clear();
		Arrays.fill(dist, -1);
		dist[t] = 0;
		q.add(t);

		// Go backwards from sink looking for source.
		// We just care to mark distances left to the sink.
		while(!q.isEmpty()) {
			int node = q.poll();
			if(node == s)
				return true;
			for(Edge e : adj[node]) {
				if(e.rev.cap > e.rev.flow && dist[e.v2] == -1) {
					dist[e.v2] = dist[node] + 1;
					q.add(e.v2);
				}
			}
		}

		// Augmenting paths exist iff we made it back to the source.
		return dist[s] != -1;
	}

	// Runs inner DFS in Dinic's, from node pos with a flow of min.
	public int dfs(int pos, int min) {

		// Made it to the sink, we're good, return this as our max flow for the augmenting path.
		if(pos == t)
			return min;
		int flow = 0;

		// Try each edge from here.
		for(Edge e : adj[pos]) {
			int cur = 0;

			// If our destination isn't blocked and it's 1 closer to the sink and there's flow, we
			// can go this way.
			if(!blocked[e.v2] && dist[e.v2] == dist[pos]-1 && e.cap - e.flow > 0) {

				// Recursively run dfs from here - limiting flow based on current and what's left on this edge.
				cur = dfs(e.v2, Math.min(min-flow, e.cap - e.flow));

				// Add the flow through this edge and subtract it from the reverse flow.
				e.flow += cur;
				e.rev.flow = -e.flow;

				// Add to the total flow.
				flow += cur;
			}

			// No more can go through, we're good.
			if(flow == min)
				return flow;
		}

		// mark if this node is now blocked.
		blocked[pos] = flow != min;

		// This is the flow
		return flow;
	}

	public int flow() {
		clear();
		int ret = 0;

		// Run a top level BFS.
		while(bfs()) {

			// Reset this.
			Arrays.fill(blocked, false);

			// Run multiple DFS's until there is no flow left to push through.
			ret += dfs(s, oo);
		}
		return ret;
	}

	// Just resets flow through all edges to be 0.
	public void clear() {
		for(ArrayList<Edge> edges : adj)
			for(Edge e : edges)
				e.flow = 0;
	}
}

