Problem:
ペンキの色

問題

情報オリンピックの宣伝のために,長方形のベニヤ板にペンキを塗り看板を制作したい.ベニヤ板には色を塗りたくないところにあらかじめ何枚かの長方形のマスキングテープが貼られている.そこでマスキングテープで区切られた領域ごとに別々の色を使いペンキを塗ることにした.例えば,図 5-1 の場合は 5 色のペンキを使う.

入力としてマスキングテープを貼る位置が与えられた時,使うペンキの色の数を求めるプログラムを作成せよ.ただし,ベニヤ板全体がマスキングテープで覆われることはなく,全てのマスキングテープの辺はベニヤ板のいずれかの辺に平行である.

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

1 行目にはベニヤ板の幅 w (1 ≤ w ≤ 1000000 となる整数) と高さ h (1 ≤ h ≤ 1000000 となる整数) がこの順に空白区切りで書かれている.

2 行目にはマスキングテープの数 n (1 ≤ n ≤ 1000 となる整数) が書かれている.
続く 3 行目以降の 2 + i 行目 (1 ≤ i ≤ n) には,i 番目に貼るマスキングテープの左下の座標 (x1 , y1 ) と,右上の座標 (x2 , y2 ) が x1 , y1 , x2 , y2 (0 ≤ x1 < x2 ≤ w, 0 ≤ y1 < y2 ≤ h となる整数) の順に空白区切りで書かれている.

ただし,ベニヤ板の左下の角の座標は (0, 0) で右上の角の座標は (w, h) である. 採点用データのうち, 配点の 30% 分は w ≤ 100, h ≤ 100, n ≤ 100 を満たす.

h, w がともに 0 のとき入力の終了を示す. データセットの数は 20 を超えない．

出力

データセットごとに使うペンキの色数を１行に出力する.

入出力例

次の例は図 5-1 の場合である.

入力例

15 6
10
1 4 5 6
2 1 4 5
1 0 5 1
6 1 7 5
7 5 9 6
7 0 9 2
9 1 10 5
11 0 14 1
12 1 13 5
11 5 14 6
0 0

出力例

5

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in JAVA (judge verdict: Memory Limit Exceeded)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;


public class Main {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		while(true){
			String[] tmpArray = br.readLine().split(" ");

			int w = Integer.parseInt(tmpArray[0]);
			int h = Integer.parseInt(tmpArray[1]);
			
			if(w == 0 && h == 0){
				break;
			}

			int n = Integer.parseInt(br.readLine());

			int x1[] = new int[n];
			int x2[] = new int[n];
			int y1[] = new int[n];
			int y2[] = new int[n];

			for(int i = 0; i < n; i++){
				tmpArray = br.readLine().split(" ");
				x1[i] = Integer.parseInt(tmpArray[0]);
				y1[i] = Integer.parseInt(tmpArray[1]);
				x2[i] = Integer.parseInt(tmpArray[2]);
				y2[i] = Integer.parseInt(tmpArray[3]);

			}

			solve(x1, y1, x2, y2, w, h);
		}
	}
	
	static void solve(int[] x1, int[] y1, int[] x2, int[] y2, int w, int h){
		int n = x1.length;
		
		boolean matrix[][] = new boolean[h][w];
		
		for(int i = 0; i < n; i++){
			paint(matrix, x1[i], y1[i], x2[i], y2[i]);
		}
		
//		showBoard(matrix);
		
		long result = 0;
		for(int i = 0; i < h; i++){
			for(int j = 0; j < w; j++){
				if(matrix[i][j] == WHITE){
					visitWithBFS(matrix, j, i);
					result++;
					
//					System.out.println("====================");
//					showBoard(matrix);
				}
			}
		}
		
		System.out.println(result);
	}
	
	static final boolean WHITE = false;
	static final boolean BLACK = true;
	
	static void visitWithBFS(boolean matrix[][], int x, int y){
		ArrayDeque<Point> que = new ArrayDeque<Point>();
		
		int dx[] = {1,0,-1,0};
		int dy[] = {0,1,0,-1};
		
		que.add(new Point(x, y));
//		matrix[y][x] = BLACK;
		while(!que.isEmpty()){
			Point tmpPoint = que.removeFirst();
			matrix[tmpPoint.y][tmpPoint.x] = BLACK;
			//四方向
			for(int i = 0; i < 4; i++){
				int newX = tmpPoint.x + dx[i];
				int newY = tmpPoint.y + dy[i];
				
				if(newX >= 0 && newX < matrix[0].length && 
						newY >= 0 && newY < matrix.length &&
						matrix[newY][newX] == WHITE){
					que.add(new Point(newX, newY));
					
				}
			}
		}
		
	}
	
	static void paint(boolean[][] matrix, int x1, int y1, int x2, int y2){
		for(int i = y1; i < y2 ; i++){
			for(int j = x1; j < x2 ; j++){
				matrix[i][j] = BLACK;
			}
		}
	}
	
	static void showBoard(boolean[][] matrix){
		for(int i = matrix.length - 1; i >= 0; i--){
			for(int j = 0; j < matrix[0].length; j++){
				if(matrix[i][j]){
					System.out.print("#");
				}
				else {
					System.out.print(".");
				}
			}
			System.out.println();
				
		}
	}

}

class Point {
	int x, y;
	
	Point(int x, int y){
		this.x = x;
		this.y = y;
	}
}