Solution Notes: This was by far the most challenging problem on the bronze contest. To solve it, we first label each of the two spots by using the recursive "flood fill" function label() that spreads out and sets every character in the spot to 1 (for the first spot) or 2 (for the second spot). This recursive function is first called when we see an 'X', after which it labels the spot containing that 'X' with 1s; it then continues scanning until it finds another 'X', after which it is called to label the spot containing that 'X' with 2s. Each time label() is called, it marks a single character and then recursively tries to visit the neighbors of that character, stopping any time we land on a character that isn't 'X'. One concern with this approach is sometimes that if the input grid is large enough, then we may run out of stack space if the label() function recurses too deeply. Fortunately, the grid here is small enough that this is not a concern (if you want to be particularly careful about this issue, you can explicitly allocate and manage the stack of recursive locations to visit, although this is a bit more code).

Once our spots are labeled, we want to find the '1' character and the '2' character that are closest together (i.e., the two characters that we need to join with a path to merge the two spots). Distance here is measured by taking the sum of absolute difference in coordinates - this is sometimes called "Manhattan" or "L1" distance. Since the grid is small enough, we can simply loop over all possible pairs of '1' characters and '2' characters and test the distance between each. If the grid was much larger, we would need to use slightly more sophisticated techniques, such as for example a breadth-first search (which is more of a silver-level technique) to quickly compute the shortest path distance from every character in the grid to a spot.



#include <stdio.h>
#define MAX_N 50
#define MAX_M 50

char G[MAX_N][MAX_M+1];
int N, M;

int label(int r, int c, char ch)
{
  if (G[r][c]!='X') return;
  G[r][c] = ch;
  if (r>0) label(r-1,c,ch);
  if (c>0) label(r,c-1,ch);
  if (r<N-1) label(r+1,c,ch);
  if (c<M-1) label(r,c+1,ch);
}

int abs(x)
{
  if (x>=0) return x;
  return -x;
}

int mindist(void)
{
  int r1, r2, c1, c2, min=MAX_N+MAX_M;
  
  for (r1=0; r1<N; r1++)
    for (c1=0; c1<M; c1++)
      if (G[r1][c1]=='1')
	for (r2=0; r2<N; r2++)
	  for (c2=0; c2<M; c2++)
	    if (G[r2][c2]=='2')
	      if (abs(r1-r2) + abs(c1-c2) < min)
		min = abs(r1-r2) + abs(c1-c2);
  return min - 1;
}

int main(void)
{
  int r, c;
  char ch='0';

  freopen ("pageant.in", "r", stdin);
  freopen ("pageant.out", "w", stdout);

  scanf ("%d %d", &N, &M);
  for (r=0; r<N; r++)
    scanf ("%s", &G[r]);

  for (r=0; r<N; r++)
    for (c=0; c<M; c++)
      if (G[r][c] == 'X') 
	label(r,c,++ch);
  
  printf ("%d\n", mindist());
  return 0;
}