Problem:
Problem B: Matrix Operations

Problem

要素が1と0からなるn×nの行列に対して、以下の種類の操作を行うプログラムを作成せよ。

部分行列と角度(0,90,180,270,360)が与えられるのでその分だけ時計回りに回転させる。

部分行列が与えられるので値を反転させる。

行が与えられるので左に1個シフトし、はみ出た分は右端に移動する。

行が与えられるので右に１個シフトし、はみ出た分は左端に移動する。

行(r),列(c)が与えられる。

Step1：現在のセルを(r,c)にする。

Step2：現在のセルの値を反転する。

Step3：隣接するセルのうち、値が現在のセルの反転前の値と等しいセルに対し、Step2とStep3の処理を行う。

ここで、セル(i,j)に隣接するセルとは、(i-1,j),
(i+1,j),(i,j-1),(i,j+1)の４つである。

Input

n m
a1,1 a1,2 ... a1,n
a2,1 a2,2 ... a2,n
:
an,1 an,2 ... an,n
Operation1
Operation2
:
Operationm

入力の最初に2つの整数nとmが空白区切りで与えられる。 nは行列のサイズ、mは操作の数を表している。

次にグリッドの情報がn行で与えられ、グリッドの情報のi行目にはn個の整数
ai,jが空白区切りで与えられる。ai,jには0か1が与えられる。

次に1行で表される各Operationiがm個与えられる。
Operationi の最初の入力はo(操作の種類)が入力される。

oが0のときは回転(Rotate)を表している。
続く入力は、r c size angle(行、列、サイズ、角度) が空白区切りで与えられる。
左上(r,c)から右下(r+size-1,c+size-1)が部分行列となる。
正方行列になることは保証されている。

oが1のときは反転(Reversal)を表している。
また、続く入力は、r c size (行、列、サイズ) が空白区切りで与えられる。
左上(r,c)から右下(r+size-1,c+size-1)が部分行列となる。
正方行列になることは保証されている。

oが2のときは左シフト(Left shift)を表している。
また、続く入力は r(行) が与えられる。

oが3のときは右シフト(Right shift)を表している。
また、続く入力は r(行) が与えられる。

oが4のときは島反転(Island reversal)を表している。
また、続く入力は r c(行、列) が空白区切りで与えられる。

Constraints

入力は以下の条件を満たす。

1 ≤ n,r,c,size ≤ 15

1 ≤ m ≤ 100

0 ≤ o ≤ 4

1 ≤ r+size-1,c+size-1 ≤ 15

0 ≤ angle ≤ 360

Output

生成された行列を出力して下さい。

Sample Input 1

3 1
1 1 0
0 1 1
1 0 1
0 2 2 2 90

Sample Output 1

1 1 0
0 0 1
1 1 1

Sample Input 2

5 2
0 0 0 0 0
1 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
3 2
4 2 2

Sample Output 2

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

Sample Input 3

5 2
1 1 1 0 1
1 0 0 0 0
0 0 0 1 1
0 1 0 0 0
0 1 1 1 0
1 3 3 3
0 1 1 5 90

Sample Output 3

0 0 0 1 1
1 1 0 0 1
0 1 1 0 1
0 1 0 0 0
1 1 0 0 1

Solution in JAVA (judge verdict: Accepted)

import java.util.*;

public class Main {
	boolean[][] matrix;
	int n, m;
	
	void print(){
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				if(j!=0) System.out.print(" ");
				if(matrix[i][j]==true) System.out.print(1);
				else System.out.print(0);
			}
			System.out.println();
		}
	}
	
	void Rotate(int r, int c, int size, int angle){
		boolean[][] temp = new boolean[size][size];
		for(int k=0;k<angle/90;k++){
			for(int i=0;i<size;i++){
				for(int j=0;j<size;j++){
					temp[i][j] = matrix[r+i][c+j];
				}
			}
			for(int i=0;i<size;i++){
				for(int j=0;j<size;j++){
					matrix[r+i][c+j] = temp[size-1-j][i];
				}
			}
		}
	}
	
	void Island(int r, int c){
		boolean f = matrix[r][c];
		int py = r;
		int px = c;
		int sy, sx;
		int[] a = new int[]{0,0,1,-1};
		int[] b = new int[]{1,-1,0,0};
		ArrayDeque<Integer> y = new ArrayDeque<Integer>();
		ArrayDeque<Integer> x = new ArrayDeque<Integer>();
		y.add(r);
		x.add(c);
		matrix[py][px] ^= true;
		while(y.size()!=0){
			py = y.poll();
			px = x.poll();
			for(int i=0;i<4;i++){
				sy = py+a[i];
				sx = px+b[i];
				if(0<=sy && sy<=n-1 && 0<=sx && sx<=n-1){
					if(matrix[sy][sx]==f){
						y.offer(sy);
						x.offer(sx);
						matrix[sy][sx] ^= true;
					}
				}
			}
		}
	}
	
	void run(){
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		matrix = new boolean[n][n];
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				int p = sc.nextInt();
				if(p==1) matrix[i][j] = true;
			}
		}
		for(int i=0;i<m;i++){
			int o = sc.nextInt();
			int r = sc.nextInt()-1;
			if(o==0){
				int c = sc.nextInt()-1;
				int size = sc.nextInt();
				int angle = sc.nextInt();
				if(angle==90 || angle==180 || angle==270) Rotate(r, c, size, angle);
			}else if(o==1){
				int c = sc.nextInt()-1;
				int size = sc.nextInt();
				for(int j=0;j<size;j++){
					for(int k=0;k<size;k++) matrix[r+j][c+k] ^= true;
				}
			}else if(o==2){
				boolean f = matrix[r][0];
				for(int j=0;j<n-1;j++) matrix[r][j] = matrix[r][j+1];
				matrix[r][n-1] = f;
			}else if(o==3){
				boolean f = matrix[r][n-1];
				for(int j=n-1;j>0;j--) matrix[r][j] = matrix[r][j-1];
				matrix[r][0] = f;
			}else if(o==4){
				int c = sc.nextInt()-1;
				Island(r, c);
			}
		}
		print();
	}
	
	public static void main(String[] args) {
		new Main().run();
	}

}