Problem:
問題文

お菓子の魔女 CHARLOTTE は巴マミとクッキーゲームを楽しんでいる．クッキーゲームは 8\times 8 の格子状に区切られたテーブルクロスの上にチーズクッキーとチョコレートクッキーを置いて行われる．各格子には高々 1 個のチョコレートクッキーまたはチーズクッキーしか置くことはできない．

お菓子の魔女はチーズクッキーを，巴マミはチョコレートクッキーを交互に置いてゲームを行う．自分のクッキーを置いたあと，そのクッキーから上下左右斜めの各 8 方向について，置くクッキーとすでに置いていた自分のクッキーの間に相手のクッキーのみが直線に並んでいた場合に，その挟まれた相手のクッキーのすべてが自分のクッキーで置き換えられる．クッキーゲームのプレイヤーは自分のターンが回ってきた時，1 つ自分のクッキーを置くことができる．ただし，相手のクッキーを少なくとも 1 つ以上自分のクッキーに置き換えられなければならない．そのような置き場がない場合，自分のターンをパスをしなければならない．

お菓子の魔女も巴マミも考えるのが少々苦手である．そこで，回ってきたターン毎にそのターンの中で置き換えられるクッキーの数を最大化することを考えることにした．巴マミのターンのときに置き換えられるクッキーの数を最大にするようなクッキーを置く場所の候補が複数ある場合は，より上の場所を，それでも複数ある場合はより左の場所を選択することにした．また同様に，お菓子の魔女のターンのときに候補が複数ある場合はより下の場所を，それでも複数ある場合はより右の場所を選択することにした．

テーブルクロスに置かれたクッキーの状態が与えられるので，巴マミからはじめ，彼女たちがそこからクッキーゲームを行い，共に新たなクッキーが置けなくなるまでゲームを続けた時のテーブルクロスの上に置かれたクッキーの状態を求めよ．

入力形式

入力は以下の形式で与えられる．

s_{11} s_{12} ... s_{18}\\
s_{21} s_{22} ... s_{28}\\
...\\
s_{81} s_{82} ... s_{88}\\

s_{ij} はテーブルクロスに置かれたクッキーの初期状態を表す文字で，上から i 行目，左から j 列目の格子の状態を表す．チョコレートクッキーが置かれているときs_{ij}は 'o' であり，チーズクッキーが置かれているときは 'x', 何も置かれていないときは '.' となる．

出力形式

クッキーゲームが行われた後のテーブルクロスの上に置かれたクッキーの状態を，入力形式と同じ形式で出力せよ．

制約

s_{ij} は 'o', 'x', '.' のいずれかである．

入出力例

入力例 1

ooox....
.x......
ooo.....
........
........
........
........
........

出力例1

ooooo...
.o......
ooo.....
...o....
....o...
........
........
........

入力例 2

........
........
........
...ox...
...xo...
........
........
........

出力例 2

xxxxxxxx
xxxooxxx
xxxxooxx
xxxxxxxx
ooxxooox
ooxoooox
oxooooox
ooooooox

入力例 3

........
........
..ooo...
..oxo...
..ooo...
........
........
........

出力例 3

........
........
..ooo...
..ooo...
..ooo...
.....o..
......o.
........

Problem Setter: Flat35

Solution in JAVA (judge verdict: Accepted)

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

import static java.lang.Integer.parseInt;

/**
 * Dessert Witch
 */
public class Main {

	static final int[][] DIR = {
			{1, 1},     //0
			{1, 0},     //1
			{1, -1},    //2
			{0, 1},     //3
			{-1, -1},   //4
			{-1, 0},    //5
			{-1, 1},    //6
			{0, -1},    //7
	};

	static char[][] TABLE = new char[10][10];

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line;
		//String[] words;

		for (int i = 0; i < 10; i++) {
			Arrays.fill(TABLE[i], ' ');
		}

		for (int i = 1; i <= 8; i++) {
			line = br.readLine();
			for (int j = 0; j < 8; j++) {
				TABLE[i][j + 1] = line.charAt(j);
			}
		}

		//solve
		boolean hasNext = true;
		while (hasNext) {
			hasNext = false;
			hasNext |= Mami();
			hasNext |= Witch();
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 1; i <= 8; i++) {
			for (int j = 1; j <= 8; j++) {
				sb.append(TABLE[i][j]);
			}
			sb.append('\n');
		}
		System.out.print(sb.toString());

	} //end main

	static boolean Mami() {

		List<int[]> list = search('o');


		if (!list.isEmpty()) {
			Collections.sort(list, new Comparator<int[]>() {
				@Override
				public int compare(int[] o1, int[] o2) {
					if (o1[4] != o2[4]) {
						return Integer.compare(o2[4], o1[4]);
					} else {
						if (o1[0] != o2[0]) {
							return Integer.compare(o1[0], o2[0]);
						} else {
							return Integer.compare(o1[1], o2[1]);
						}
					}
				}
			});
			put('o', list);
			return true;
		} else {
			return false;
		}
	}

	static boolean Witch() {

		List<int[]> list = search('x');

		if (!list.isEmpty()) {
			Collections.sort(list, new Comparator<int[]>() {
				@Override
				public int compare(int[] o1, int[] o2) {
					if (o1[4] != o2[4]) {
						return Integer.compare(o2[4], o1[4]);
					} else {
						if (o1[0] != o2[0]) {
							return Integer.compare(o2[0], o1[0]);
						} else {
							return Integer.compare(o2[1], o1[1]);
						}
					}
				}
			});
			put('x', list);
			return true;
		} else {
			return false;
		}
	}

	static List<int[]> search(char p) {

		char t;
		List<int[]> list = new ArrayList<>();

		if (p == 'o') t = 'x';
		else t = 'o';

		for (int i = 1; i <= 8; i++) {
			for (int j = 1; j <= 8; j++) {
				if (TABLE[i][j] == p) {
					for (int k = 0; k < 8; k++) {
						int y, x;
						y = i + DIR[k][0];
						x = j + DIR[k][1];
						int[] res = null;
						if (TABLE[y][x] == t) {
							res = searchS(t, y, x, k, 1);
							if (res != null) {
								list.add(res);
							}
						}
					}
				}
			}
		}

		//sum up
		if (list.size() > 1) {
			int[][] sum = new int[10][10];
			for (int[] l : list) {
				sum[l[0]][l[1]] += l[3];
			}
			for (int[] l : list) {
				l[4] = sum[l[0]][l[1]];
			}
		}
		return list;
	}

	static int[] searchS(char t, int y, int x, int dir, int c) {

		int ny, nx;
		ny = y + DIR[dir][0];
		nx = x + DIR[dir][1];

		if (TABLE[ny][nx] == t) {
			return searchS(t, ny, nx, dir, c + 1);
		} else if (TABLE[ny][nx] == '.') {
			return new int[]{ny, nx, dir, c, c};
		} else {
			return null;
		}
	}

	static void put(char p, List<int[]> list) {

		int sy, sx;
		sy = list.get(0)[0];
		sx = list.get(0)[1];

		TABLE[sy][sx] = p;

		for (int i = 0; i < list.size(); i++) {
			if (list.get(i)[0] == sy && list.get(i)[1] == sx) {
				int y, x, dir, c;
				y = sy;
				x = sx;
				dir = (list.get(i)[2] + 4) % 8;
				c = list.get(i)[3];
				for (int j = 0; j < c; j++) {
					y += DIR[dir][0];
					x += DIR[dir][1];
					TABLE[y][x] = p;
				}
			} else {
				break;
			}
		}
	}
}