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.IOException;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) throws IOException {

		new Main().run();
	}

	private void run() throws IOException {
		Scanner scanner = new Scanner(System.in);
		int[] dy = { -1, -1, -1, 0, 0, 1, 1, 1 };
		int[] dx = { -1, 0, 1, -1, 1, -1, 0, 1 };
		char[][] map = new char[8][8];
		for (int i = 0; i < 8; i++)
			map[i] = scanner.next().toCharArray();
		char my, en;
		int u = 0;
		int flag = 0;
		while (true) {
			if (u == 0) {
				my = 'o';
				en = 'x';
			} else {
				my = 'x';
				en = 'o';
			}
			int cnt = 0, ey = 0, ex = 0, dir = 0;
			for (int y = 0; y < 8; y++)
				for (int x = 0; x < 8; x++) {
					int hy = u == 0 ? y : 7 - y;
					int hx = u == 0 ? x : 7 - x;
					if (map[hy][hx] != '.')
						continue;
					int cc = 0, ndir = 0;
					for (int i = 0; i < 8; i++) {
						int c = 0;
						while (true) {
							int ny = hy + dy[i] * (c + 1);
							int nx = hx + dx[i] * (c + 1);
							if (!isOK(ny, nx))
								break;
							if (map[ny][nx] == en) {
								c++;
								continue;
							} else if (map[ny][nx] == my && c != 0) {
								cc += c;
								ndir |= (1 << i);
							}
							break;
						}
					}
					if (cnt >= cc)
						continue;
					cnt = cc;
					ey = hy;
					ex = hx;
					dir = ndir;
				}
			u = 1 - u;
			if (cnt == 0) {
				flag++;
				if (flag == 2)
					break;
			} else {
				flag = 0;
				map[ey][ex] = my;
				for (int i = 0; i < 8; i++) {
					if (((dir >> i) & 1) == 0)
						continue;
					int k = 1;
					while (true) {
						int ny = ey + dy[i] * k;
						int nx = ex + dx[i] * k;
						if (map[ny][nx] == my)
							break;
						map[ny][nx] = my;
						k++;
					}
				}
			}

		}
		for (char[] ans : map)
			System.out.println(ans);

	}

	private boolean isOK(int ny, int nx) {
		return 0 <= ny && ny < 8 && 0 <= nx && nx < 8;
	}
}