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.Scanner;

public class Main{
	Scanner sc;
	int INF = 1<<27;
	
	int x, y;
	boolean done[][];
	byte[][] map;
	
	int search( int cnt, int sum, byte c ){
		if( sum == y*x ){
			return cnt;
		}
		
		int ans = INF;
		
		byte[][] dup = new byte[y][x];
		for( int j = 0; j < y; ++j ){
			for( int k = 0; k < x; ++k ){
				dup[j][k] = map[j][k];
			}
		}
		
		for( byte i = 0; i < 3; ++i ){
			if( i == c )continue;
			
			done = new boolean[y][x];
			int res = fill( i, 0, 0, c );
			
			if( res != sum ){
				ans = Math.min( ans, search( cnt + 1, res, i ) );
			}
			
			for( int j = 0; j < y; ++j ){
				for( int k = 0; k < x; ++k ){
					map[j][k] = dup[j][k];
				}
			}
		}
		
		return ans;
	}
	
	void run(){
		sc = new Scanner(System.in);
		
		while(true){
			x = ni();
			y = ni();
			if( (x|y) == 0 ){
				break;
			}
			
			map = new byte[y][x];
			for( int i = 0; i < y; ++i ){
				for( int j = 0; j < x; ++j ){
					map[ i ][ j ] = nc();
				}
			}
			
			System.out.println( search( 0, 0, map[0][0] ) );
		}
		
		sc.close();
	}
	
	int[][] ofs = { {0,1}, {1,0} };
	int count( byte color, int y, int x ){
		if( x >= this.x || y >= this.y )return 0;
		if(done[y][x])return 0;

		int cnt = 0;
		if( map[y][x] == color ){
			++cnt;
			done[y][x] = true;
			for( int i = 0; i < 2; ++i ){
				cnt += count( color, y + ofs[ i ][ 1 ], x + ofs[ i ][ 0 ] );
			}			
		}
		
		return cnt;
	}
	int count( byte color, int y, int x, byte trg, boolean flag ){
		if( x >= this.x || y >= this.y )return 0;
		if(done[y][x])return 0;

		int cnt = 0;
		if( !flag && map[y][x] == color ){
			++cnt;
			done[y][x] = true;
			for( int i = 0; i < 2; ++i ){
				cnt += count( color, y + ofs[ i ][ 1 ], x + ofs[ i ][ 0 ], trg, false );
			}			
		}else{
			if( map[y][x] == trg ){
				++cnt;
				done[y][x] = true;
				for( int i = 0; i < 2; ++i){
					cnt += count( color, y + ofs[ i ][ 1 ], x + ofs[ i ][ 0 ], trg, true );
				}
			}
		}
		
		return cnt;
	}
	
	int fill( byte color, int y, int x, byte trg ){
		if( x >= this.x || y >= this.y )return 0;
		if(done[y][x])return 0;
		
		int cnt = 0;
		
		if(map[y][x] == trg){
			map[y][x] = color;
			done[y][x] = true;
			++cnt;
			
			for( int i = 0; i < 2; ++i ){
				cnt += fill( color, y + ofs[ i ][ 1 ], x + ofs[ i ][ 0 ], trg );
			}
		}else{
			if(map[y][x] == color){
				done[y][x] = true;
				++cnt;
				
				for( int i = 0; i < 2; ++i ){
					cnt += fill( color, y + ofs[ i ][ 1 ], x + ofs[ i ][ 0 ], color );
				}
			}
		}
		
		return cnt;
	}
	
	int ni(){ return sc.nextInt(); }
	byte nc(){
		switch(sc.next().charAt(0)){
		case 'R' : return 0;
		case 'G' : return 1;
		case 'B' : return 2;
		default : return -1;
		}
	}
	
	public static void main(String[] args){
		new Main().run();
	}
}