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: Wrong Answer)

import java.util.HashSet;
import java.util.Set;

//Filling Game
public class Main{

	class Scanner {
		int nextInt() {
			try {
				int c = System.in.read();
				while (c != '-' && (c < '0' || '9' < c))
					c = System.in.read();
				if (c == '-') return -nextInt();
				int res = 0;
				do {
					res *= 10;
					res += c - '0';
					c = System.in.read();
				} while ('0' <= c && c <= '9');
				return res;
			} catch (Exception e) {
				return -1;
			}
		}
		String next() {
			try {
				StringBuilder res = new StringBuilder("");
				int c = System.in.read();
				while (Character.isWhitespace(c))
					c = System.in.read();
				do {
					res.append((char) c);
				} while (!Character.isWhitespace(c = System.in.read()));
				return res.toString();
			} catch (Exception e) {
				return null;
			}
		}
	}
	
	int h, w;
	int[][] a;
	int[][] d = {{-1,0},{0,1},{1,0},{0,-1}};
	boolean[][][] u;
	int[] c;
	boolean[][] con;
	int sum;
	
	boolean ok(int i, int j){
		return 0<=i&&i<h&&0<=j&&j<w;
	}
	
	void chain(int i, int j, int K, int id){
		if(con[i][j]||u[id][i][j]||a[i][j]!=K)return;
		u[id][i][j] = true;
		c[id]++;
		for(int k=0;k<4;k++){
			int ni = i+d[k][0], nj = j+d[k][1];
			if(ok(ni, nj))chain(ni, nj, K, id);
		}
	}
	
	void f(int i, int j, int K){
		if(con[i][j]||a[i][j]!=K)return;
		con[i][j] = true;
		sum++;
		for(int k=0;k<4;k++){
			int ni = i+d[k][0], nj = j+d[k][1];
			if(ok(ni, nj))f(ni, nj, K);
		}
	}
	
	void run(){
		Scanner sc = new Scanner();
		for(;;){
			w = sc.nextInt(); h = sc.nextInt();
			if((w|h)==0)break;
			a = new int[h][w];
			con = new boolean[h][w];
			for(int i=0;i<h;i++)for(int j=0;j<w;j++){
				char c = sc.next().charAt(0);
				a[i][j] = c=='R'?0:c=='G'?1:2;
			}
			sum = 0;
			f(0, 0, a[0][0]);
			int res = 0;
			for(;sum<h*w;res++){
//				p();
				Set<Integer> s1 = new HashSet<Integer>(), s2 = new HashSet<Integer>();
				int c1 = (a[0][0]+1)%3, c2 = (a[0][0]+2)%3;
				for(int i=0;i<h;i++)for(int j=0;j<w;j++){
					if(con[i][j])continue;
					for(int k=0;k<4;k++){
						int ni = i+d[k][0], nj = j+d[k][1];
						if(ok(ni, nj)&&con[ni][nj]){
							if(a[i][j]==c1)s1.add(i*w+j);
							else if(a[i][j]==c2)s2.add(i*w+j);
							break;
						}
					}
				}
				u = new boolean[2][h][w];
				c = new int[2];
				for(int x:s1)chain(x/w, x%w, c1, 0);
				for(int x:s2)chain(x/w, x%w, c2, 1);
				if(c[1]<c[0]){
					for(int i=0;i<h;i++)for(int j=0;j<w;j++){
						if(con[i][j])a[i][j] = c1;
						else if(u[0][i][j]){
							con[i][j] = true; sum++;
						}
					}
				}
				else{
					for(int i=0;i<h;i++)for(int j=0;j<w;j++){
						if(con[i][j])a[i][j] = c2;
						else if(u[1][i][j]){
							con[i][j] = true; sum++;
						}
					}
				}
			}
			System.out.println(res);
		}
	}
	
//	void p(){
//		for(int i=0;i<h;i++){
//			for(int j=0;j<w;j++)System.out.print(con[i][j]?"o":"x");
//			System.out.println();
//		}
//		System.out.println();
//	}
	
/*
10 10
B R G R B R G B R G
G B R B G B R G B R
R G B G B G B R G B
B R G R G R G B R G
G B R G R G B R G B
R G B R G B R B R G
B R G B R G B R G B
G B R G B R G B R G
B R G B G B R G B R
R B R G B G B R G B
0 0
 */
	
	public static void main(String[] args) {
		new Main().run();
	}
}