Problem:
Problem A: Ennichi

縁日に来たうさぎが, ある出店のゲームの景品がキャロットケーキであるのを見つけた. このゲームのルールは以下の通りである.

縦h マス× 横w マスの格子状のフィールドがあり, 各マスにつき高々1 個のブロックが置かれる. 各ブロックにはアルファベット大文字(‘A’ - ‘Z’) のいずれかで表される色がついている. 同色のブロックが縦または横に一直線上にn 個以上連続して並ぶと, それらのブロックは消滅する.

参加者は横に隣り合う2 つのマスを選んで, それらの状態を互いに入れ替える操作ができる. ブロックの入れ替え, 消滅, 落下によってブロックの有るマスの1 つ下のマスにブロックが無くなると, このブロックは落下する. このときふたたび同色のブロックがn 個以上並ぶと消滅する. ただし, ブロックの消滅は, 落下するブロックが存在する間は起こらず, すべてのブロックの落下が終了したタイミングで同時に起こる.

1 回の操作でフィールド上のすべてのブロックを消滅させると, このゲームは成功となり景品のケーキを得ることができる. うさぎは1 回分の参加費で確実にケーキを手に入れたく, それができない場合は参加したくない. ゲーム開始時のフィールドの状態から, うさぎがこのゲームに参加すべきであるか答えよ.

Input

入力の一行目にはh, w, n がスペースで区切られて与えられる.

2 ≤ h,w, n ≤ 30

続くh 行にはフィールドの状態が上から順に与えられる. アルファベット大文字はブロックを, ‘.’ は空きマスを表す. 与えられるフィールドの状態には, 縦あるいは横にn 個以上連続する同色のブロックはなく, 落下する状態にあるブロックもない. 1 個以上のブロックが存在する.

Output

うさぎがこのゲームに参加すべきであるなら”YES”を, そうでないなら”NO”を一行に出力せよ.

Sample Input 1

4 6 3
......
...Y..
...Y..
RRYRYY

Sample Output 2

YES

Sample Input 1

4 6 3
......
...Y..
...Y..
RRYRY.

Sample Output 2

NO

Solution in JAVA (judge verdict: Wrong Answer)

import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) throws IOException {
		Scanner scanner = new Scanner(System.in);
		int height = scanner.nextInt();
		int width = scanner.nextInt();
		int n = scanner.nextInt();

		char[][] field = new char[height][width];// フィールド状態
		for (int i = 0; i < field.length; i++) {
			String line = scanner.next();
			for (int j = 0; j < field[i].length; j++) {
				field[i][j] = line.charAt(j);
			}
		}
		scanner.close();

		for (int i = 0; i < height * width; i++) {
			int ih = i / width;
			int iw = i % width;
			if (field[ih][iw] == '.') {
				continue;
			}
			for (int j = i + 1; j < height * width; j++) {
				int jh = j / width;
				int jw = j % width;
				if (field[jh][jw] == '.' || field[jh][jw] == field[ih][iw]) {
					continue;
				}

				// フィールドを複製する
				char[][] cloneField = new char[height][width];
				for (int k = 0; k < cloneField.length; k++) {
					for (int k2 = 0; k2 < cloneField[k].length; k2++) {
						cloneField[k][k2] = field[k][k2];
					}
				}

				// 入れ替える
				char tmp = cloneField[ih][iw];
				cloneField[ih][iw] = cloneField[jh][jw];
				cloneField[jh][jw] = tmp;

				while (true) {
					// 消えるところをリストアップする
					Deque<Integer> toVanish = new ArrayDeque<Integer>();
					for (int row = 0; row < cloneField.length; row++) {
						int start = -1;
						for (int l = 1; l < cloneField[row].length + 1; l++) {
							if (l < cloneField[row].length
									&& start == -1
									&& cloneField[row][l - 1] != '.'
									&& cloneField[row][l] == cloneField[row][l - 1]) {
								start = l - 1;
							} else if (l == cloneField[row].length
									|| cloneField[row][l] != cloneField[row][l - 1]) {
								if (start != -1 && l - start >= n) {
									for (int t = 0; t < cloneField[row].length; t++) {
										if (t >= start && t < l) {
											toVanish.add(width * row + t);
										}
									}
								}
								start = -1;
							}
						}
					}

					for (int column = 0; column < cloneField[0].length; column++) {
						int start = -1;
						for (int l = 1; l < cloneField.length + 1; l++) {
							if (l < cloneField.length
									&& start == -1
									&& cloneField[l - 1][column] != '.'
									&& cloneField[l][column] == cloneField[l - 1][column]) {
								start = l - 1;
							} else if (l == cloneField.length
									|| cloneField[l][column] != cloneField[l - 1][column]) {
								if (start != -1 && l - start >= n) {
									for (int t = 0; t < cloneField.length; t++) {
										if (t >= start && t < l) {
											toVanish.add(width * t + column);
										}
									}
								}
								start = -1;
							}

						}

					}

					// 消えるところがなければ終了
					if (toVanish.isEmpty()) {
						break;
					}

					// 消えるところを消す
					while (!toVanish.isEmpty()) {
						int k = toVanish.poll();
						int ki = k / width;
						int kj = k % width;
						cloneField[ki][kj] = '.';
					}

					// 落下処理
					for (int column = 0; column < cloneField[0].length; column++) {
						Deque<Character> characters = new ArrayDeque<Character>();
						for (int k = height - 1; k >= 0; k--) {
							if (cloneField[k][column] != '.') {
								characters.add(cloneField[k][column]);
							}
						}
						for (int k = height - 1; k >= 0; k--) {
							if (!characters.isEmpty()) {
								cloneField[k][column] = characters.pollFirst();
							} else {
								cloneField[k][column] = '.';
							}
						}
					}

				}

				boolean toApply = true;
				check: for (int k = 0; k < cloneField.length; k++) {
					for (int k2 = 0; k2 < cloneField[k].length; k2++) {
						if (cloneField[k][k2] != '.') {
							toApply = false;
							break check;
						}
					}
				}

				if (toApply) {
					System.out.println("YES");
					return;
				}
			}
		}

		System.out.println("NO");
		return;

	}
}