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

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;

public class Main {
	
	public static final int MAX_N = 1000;
	public static final int MAX_SIZE = MAX_N * 4;
	
	public static final int[][] move_dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
	
	public static boolean is_ok(int x, int y, int w, int h){
		if(x < 0 || x >= w || y < 0 || y >= h){
			return false;
		}else{
			return true;
		}
	}
	
	public static void bfs(int x, int y, final int w, final int h, short[][] masked, boolean[][] visited){
		LinkedList<Integer> x_queue = new LinkedList<Integer>();
		LinkedList<Integer> y_queue = new LinkedList<Integer>();
		
		visited[y][x] = true;
		x_queue.add(x);
		y_queue.add(y);
		
		while(!x_queue.isEmpty()){
			final int c_x = x_queue.poll();
			final int c_y = y_queue.poll();
			
			for(int[] move : move_dir){
				final int nx = c_x + move[0];
				final int ny = c_y + move[1];
			
				if(!is_ok(nx, ny, w, h)){
					continue;
				}else if(masked[ny][nx] > 0){
					continue;
				}else if(visited[ny][nx]){
					continue;
				}
			
				visited[ny][nx] = true;
				x_queue.add(nx);
				y_queue.add(ny);
				//bfs(nx, ny, w, h, masked, visited);
			}
		}
	}
	
	
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		short[][] masked = new short[MAX_SIZE + 1][MAX_SIZE + 1];
		boolean[][] visited = new boolean[MAX_SIZE + 1][MAX_SIZE + 1];
		
		TreeSet<Integer> x_set = new TreeSet<Integer>();
		TreeSet<Integer> y_set = new TreeSet<Integer>();
		ArrayList<Integer> x_list = new ArrayList<Integer>();
		ArrayList<Integer> y_list = new ArrayList<Integer>();
		
		int[][] data = new int[MAX_N][4];
		
		while (true) {
			final int w = sc.nextInt();
			final int h = sc.nextInt();
			
			if(w == 0 && h == 0){
				break;
			}
			
			final int n = sc.nextInt();
			
			x_set.clear();
			y_set.clear();
			x_list.clear();
			y_list.clear();
			
			//x_set.add(0);
			//x_set.add(w);
			//y_set.add(0);
			//y_set.add(h);
			
			for(int i = 0; i < n; i++){
				final int x1 = sc.nextInt();
				final int y1 = sc.nextInt();
				final int x2 = sc.nextInt() - 1;
				final int y2 = sc.nextInt() - 1;
				
				data[i][0] = x1;
				data[i][1] = y1;
				data[i][2] = x2;
				data[i][3] = y2;
				
				x_set.add(x1 - 1);
				x_set.add(x1);
				x_set.add(x2);
				x_set.add(x2 + 1);
				
				y_set.add(y1 - 1);
				y_set.add(y1);
				y_set.add(y2);
				y_set.add(y2 + 1);
			}
			
			x_list.addAll(x_set);
			y_list.addAll(y_set);
			
			final int w_c = x_list.size();
			final int h_c = y_list.size();
			
			for(int i = 0; i <= h_c; i++){
				for(int j = 0; j <= w_c; j++){
					masked[i][j] = 0;
				}
			}
			
			for(int i = 0; i < n; i++){
				final int x1 = Collections.binarySearch(x_list, data[i][0]);
				final int y1 = Collections.binarySearch(y_list, data[i][1]);
				final int x2 = Collections.binarySearch(x_list, data[i][2]);
				final int y2 = Collections.binarySearch(y_list, data[i][3]);
				
				//System.out.println(x1 + " " + y1 + " , " + x2 + " " + y2);
				
				masked[y1][x1]++;
				masked[y1][x2 + 1]--;
				masked[y2 + 1][x1]--;
				masked[y2 + 1][x2 + 1]++;
			}

			/*
			System.out.println(x_list);
			for(int i = h_c - 1; i >= 0; i--){
				for(int j = 0; j < w_c; j++){
					System.out.print(masked[i][j] + " ");
				}
				System.out.println();
			}
			System.out.println(y_list);
			*/
			
			for(int i = 0; i < h_c; i++){
				for(int j = 1; j < w_c; j++){
					masked[i][j] += masked[i][j-1];
				}
			}
			
			for(int j = 0; j < w_c; j++){
				for(int i = 1; i < h_c; i++){
					masked[i][j] += masked[i-1][j];
				}
			}
			
			for(int i = 0; i < w_c; i++){
				masked[h_c - 1][i] = 1;
				masked[0][i] = 1;
			}
			
			for(int i = 0; i < h_c; i++){
				masked[i][w_c-1] = 1;
				masked[i][0] = 1;
			}
			
			/*
			System.out.println(x_list);
			for(int i = h_c - 1; i >= 0; i--){
				for(int j = 0; j < w_c; j++){
					System.out.print(masked[i][j] + " ");
				}
				System.out.println();
			}
			System.out.println(y_list);
			*/
			
			for(int i = 0; i < h_c; i++){
				for(int j = 0; j < w_c; j++){
					visited[i][j] = false;
				}
			}
			
			int count = 0;
			for(int i = 0; i < h_c; i++){
				for(int j = 0; j < w_c; j++){
					if(masked[i][j] > 0){
						continue;
					}else if(visited[i][j]){
						continue;
					}
					
					bfs(j, i, w_c, h_c, masked, visited);
					count++;
				}
			}
			
			System.out.println(count);
		}
	}
}