#!/usr/bin/env python

# Brick
# Phil Bordelon

import os
import sys

DEBUG = os.getenv("DEBUG", False)

# Use a large number that is longer than any possible maximum
# distance for Dijkstra's.

def dijkstra(wall_dict, source, dest):

   # We're going to go through the nodes, finding the best-cost one each
   # step, ending when we get to the destination.  We start with nothing
   # more than the source node.  We prime the setup by starting with the
   # "start" (surprise!) and priming the list to visit with all nodes
   # adjacent to the start.
   visited_list = [source]
   to_visit_list = [(x, wall_dict[source]["connections"][x]) for x in wall_dict[source]["connections"]]
   to_return = BIG_NUMBER
   done = False
   while not done:

      # Find the cheapest edge in the to_visit_list.
      short_edge = (None, BIG_NUMBER)
      for elem in to_visit_list:
         if elem[1] < short_edge[1]:
            short_edge = elem

      # Visit it!  Add it to the visited list, remove all other connections
      # to it in the to_visit_list, and add nodes it connects to that we
      # haven't gotten to yet, with proper weights.
      node_to_visit, cost = short_edge

      # Strip the to_visit_list of instances of this node ...
      to_visit_list = [x for x in to_visit_list if x[0] != node_to_visit]

      # Get the new entries ...
      if DEBUG:
         print "Visiting " + repr(node_to_visit)

      # ... get all new places to visit (skipping already-visited places) ...
      new_visits = [x for x in wall_dict[node_to_visit]["connections"] if x not in visited_list]
      # ... and add them to the to_visit_list.  Also, bail if one of them is the dest.
      connections = wall_dict[node_to_visit]["connections"]
      for location in new_visits:
         if location == dest:

            # We made it to the destination node, and know what the cost of
            # transit was.
            done = True
            to_return = connections[dest] + cost
            to_visit_list.append((location, cost + connections[location]))

      if DEBUG:
         print "Left to visit: " + repr(to_visit_list)

   # Return the cost of transiting the grid.
   return to_return

def buildConnections(wall_dict, height, width):

   # In this lovely function, we build the connections between the various
   # bricks.  If two squares are adjacent to each other and have the same
   # letter representation, they're part of the same brick, and so travel
   # between them is free.  If the letter changes, though, that's a brick
   # "crossing", which counts as an actual "move."

   # First, we need to add the top and bottom "nodes."  We keep them
   # out of the dictionary at first, then add them at the end.
   top = {"connections": {}}
   bottom = {"connections": {}}

   # Now, we set paths between all nodes.  It costs 0 to move between
   # adjacent nodes that have the same letter, otherwise it costs 1.
   # This will incidentally give us the number of bricks necessary to
   # remove to get to the bottom of the wall, as you will never reenter
   # the same brick after leaving it (otherwise you could have stayed in
   # the brick in the first place, as all movement inside it costs 0.)
   for x, y in wall_dict:
      this_block = wall_dict[(x, y)]
      if x == 0:

         # Top row.  We only need to connect from the top to it, as it
         # will never be beneficial to go /back/ to the top from a lower
         # brick.  We also need to make either this transit or the one
         # to the bottom cost something; I arbitrarily chose to make this
         # one cost.
         top["connections"][(x, y)] = 1
      if x == height - 1:
         # Bottom row.  Once again, it's not worth coming back /up/ from
         # the bottom, as that's the goal, so don't bother making connections
         # back up to this block.
         this_block["connections"]["bottom"] = 0
         # Check the block below.  If it's the same letter, the cost is
         # zero; otherwise, it is one.
         below_block = wall_dict[(x + 1, y)]
         if this_block["letter"] == below_block["letter"]:

            # Make transit between this block and the one below it free.
            # We need to set the values in both directions, not just
            # down ... for reasons that are obvious if you consider how
            # devious us judges are.
            this_block["connections"][(x + 1, y)] = 0
            below_block["connections"][(x, y)] = 0

            # Ya gotsta pay the price for this transit.
            this_block["connections"][(x + 1, y)] = 1
            below_block["connections"][(x, y)] = 1

      # Do the same for the block to the right.
      if y < width - 1:
         right_block = wall_dict[(x, y + 1)]
         if this_block["letter"] == right_block["letter"]:

            # Free ride!
            this_block["connections"][(x, y + 1)] = 0
            right_block["connections"][(x, y)] = 0

            # Not so much.
            this_block["connections"][(x, y + 1)] = 1
            right_block["connections"][(x, y)] = 1

   # Finally, add the top and bottom to the dictionary.
   wall_dict["top"] = top
   wall_dict["bottom"] = bottom
if "__main__" == __name__:

   dataset_count = int(sys.stdin.readline())
   for dataset_loop in range(dataset_count):
      # Get the height and width ...
      height, width = [int(x) for x in sys.stdin.readline().strip().split()]

      # Then read the entire wall in.
      wall_dict = {}
      for i in range(height):
         block_row = sys.stdin.readline().strip()
         if len(block_row) != width:
            sys.exit("ERROR: Invalid width of line '%s' (should be %d)!" % (block_row, width))
         for j in range(width):

            # Build the block for the big ol' table.  We don't set up
            # connections between bits of bricks yet.
            wall_dict[(i, j)] = {
               "letter": block_row[j],
               "connections": {}

      # Now that we've read the wall in, build the connections.
      buildConnections(wall_dict, height, width)

      # Lastly, Dijkstra!
      print dijkstra(wall_dict, "top", "bottom")