Problem:
塗りつぶしゲーム

指で画面にタッチして操作することのできるタブレットインターフェースの技術は、ゲームの分野でも応用され、新しい操作感を持つ様々な種類のゲームが作られています。現在、ＡＺ社が開発しているゲームもその一つです。

このソフトウェア（ゲーム）の要件は以下の通りです。

画面には X 列× Y行の2次元グリッドがあります。

グリッドのセルは赤(R)、緑(G)、茶(B)の3色のいずれかで塗られています。

セルの色を変更するボタンR、G、Bがあり、このボタンが押下されると一番左上(0,0)のセルがその色に変更されます。

一番左上のセルの色が変更されると、そのセルの元の色と同じ色に塗られた隣接するすべてのセルが指定された色に変わります。すなわち、元の色が同じ色のセルでつながったセルはすべて指定された色に変更されます。

このようにグリッドを塗りつぶしていき、最終的にグリッド全体を一色にするというゲームです。少ない手順で解くと高得点が与えられます。

ＡＺ社のプログラマーであるあなたは、このゲームのロジックの一部分を開発することになりました。まずは、この最高得点を計算するため、このゲームを最短で解いた場合、最低何回選択ボタンを操作すればグリッドが一色になるかをもとめるプログラムを作ることにしました。

入力

複数のデータセットが与えられます。入力の終わりはゼロふたつで示されます。各データセットは以下の形式で与えられます。

X Y
c1,1 c2,1 ... cX,1
c1,2 c2,2 ... cX,2
:
c1,Y c2,Y ... cX,Y

1行目にグリッドの列と行のサイズ X, Y (2 ≤ X, Y ≤ 10) が与えられます。続く Y 行に i 列目 j 行目のセルの色を表す文字 ci,j が空白区切りで与えられます。

出力

データセットごとに、ボタン操作の最少回数を1行に出力します。

入力例

3 3
R G B
G G G
G B B
2 4
R G
G G
R B
B R
4 3
G G B R
G R R G
B G G R
0 0

出力例

2
4
4

Solution in JAVA (judge verdict: Accepted)

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;

public class Main {
	
	static int x, y;
	static int[][] c;
	static class State{
		int color, minstep;
		int[][] field=new int[y][x];
		State(int color, int[][] field, int minstep){
			this.color=color;
			for(int i=0; i<y; i++) {
				for(int j=0; j<x; j++) {
					this.field[i][j]=field[i][j];
				}
			}
			this.minstep=minstep;
		}
	}
	
	static void Copy(int[][] b) {
		for(int i=0; i<y; i++) {
			for(int j=0; j<x; j++) {
				c[i][j]=b[i][j];
			}
		}
	}
	static void dfs(int w, int h, int pre, int now) {
		int[] dx= {1, 0, -1, 0};
		int[] dy= {0, 1, 0, -1};
		c[h][w]=now;
		for(int i=0; i<4; i++) {
			if(w+dx[i]<0 || w+dx[i]>=x || h+dy[i]<0 || h+dy[i]>=y) continue;
			if(c[h+dy[i]][w+dx[i]]!=pre) 	continue;
			dfs(w+dx[i], h+dy[i], pre, now);
		}
	}
	
	public static void main(String[] args) {
		try(Scanner sc = new Scanner(System.in)){
			while(sc.hasNext()) {
				x=sc.nextInt();
				y=sc.nextInt();
				if(x+y==0) break;
				c=new int[y][x];
				for(int i=0; i<y; i++) {
					for(int j=0; j<x; j++) {
						String s=sc.next();
						if(s.equals("R")) {
							c[i][j]=1;
						}else if(s.equals("G")) {
							c[i][j]=2;
						}else {
							c[i][j]=3;
						}
					}
				}
				Queue<State> q=new LinkedList<>();
				//int[][] copy=new int[y][x];
				
				q.add(new State(c[0][0], c, 0));
				int count=0;
				Map<String, Integer> map=new HashMap<>();
				while(!q.isEmpty()) {
					State s=q.poll();
					boolean tf=true;
					String str="";
					for(int i=0; i<y; i++) {
						for(int j=0; j<x; j++) {
							str+=String.valueOf(s.field[i][j]);
							if(s.field[0][0]!=s.field[i][j]) {
								tf=false; 
							}
						}
					}
					if(tf) {
						count=s.minstep;
						break;
					}
					if(map.containsKey(str)) continue;
					map.put(str, s.minstep);
					
					for(int i=1; i<=3; i++) {
						if(s.color==i) continue;
						Copy(s.field);
						dfs(0, 0, s.color,i);
						q.add(new State(i, c, s.minstep+1));
					}
				}
				System.out.println(count);
			}

		}
	}
}