1
+ import java .io .BufferedReader ;
2
+ import java .io .InputStreamReader ;
3
+ import java .util .StringTokenizer ;
4
+
5
+ public class Main {
6
+
7
+ static int n , m , t , p ; // 세로, 가로, 시간, 시공의 돌풍의 위치
8
+ // 윗 부분 회전에 맞추기 위해
9
+ // 우 -> 상 -> 좌 -> 하
10
+ // 순으로 변화량을 저장
11
+ static int [] dy = { 0 , -1 , 0 , 1 };
12
+ static int [] dx = { 1 , 0 , -1 , 0 };
13
+ static int [][] board ;
14
+
15
+ public static void main (String [] args ) throws Exception {
16
+ BufferedReader br = new BufferedReader (new InputStreamReader (System .in ));
17
+ StringTokenizer st = new StringTokenizer (br .readLine ());
18
+ n = Integer .parseInt (st .nextToken ());
19
+ m = Integer .parseInt (st .nextToken ());
20
+ t = Integer .parseInt (st .nextToken ());
21
+ board = new int [n ][m ];
22
+ for (int i = 0 ; i < n ; i ++) {
23
+ st = new StringTokenizer (br .readLine ());
24
+ for (int j = 0 ; j < m ; j ++)
25
+ board [i ][j ] = Integer .parseInt (st .nextToken ());
26
+ // 마지막 시공의 돌풍의 y좌표
27
+ if (board [i ][0 ] == -1 )
28
+ p = i ;
29
+ }
30
+ // 시간만큼 시뮬레이션
31
+ while (t -- > 0 ) {
32
+ spread (); // 확산
33
+ rotate (p - 1 , 1 ); // 윗 부분 회전
34
+ rotate (p , -1 ); // 아랫 부분 회전
35
+ }
36
+ System .out .println (calculate ()); // 방 안의 먼지의 총합 계산
37
+ }
38
+
39
+ private static void spread () {
40
+ int [][] tempBoard = new int [n ][m ]; // 확산되는 양을 저장할 새로운 배열
41
+ for (int i = 0 ; i < n ; i ++)
42
+ for (int j = 0 ; j < m ; j ++)
43
+ if (board [i ][j ] > 0 ) {
44
+ int amount = board [i ][j ] / 5 ; // 확산될 양
45
+ for (int k = 0 ; k < 4 ; k ++) {
46
+ int y = i + dy [k ];
47
+ int x = j + dx [k ];
48
+ // 유효한 좌표라면 확산
49
+ if (isValid (y , x ) && board [y ][x ] != -1 ) {
50
+ tempBoard [i ][j ] -= amount ; // 확산시킨 곳의 양은 감소
51
+ tempBoard [y ][x ] += amount ; // 확산된 곳의 양은 증가
52
+ }
53
+ }
54
+ }
55
+ // 원래 방에서 확산으로 인한 변화량을 더해줌
56
+ for (int i = 0 ; i < n ; i ++)
57
+ for (int j = 0 ; j < m ; j ++)
58
+ board [i ][j ] += tempBoard [i ][j ];
59
+ }
60
+
61
+ /*
62
+ * @param s: 시공의 돌풍의 y좌표
63
+ * @param mode: 윗 회전인지 아랫 회전인지 알려주는 변수
64
+ *
65
+ * mode에 따라서 회전하는 방향이 결정됨
66
+ */
67
+ private static void rotate (int s , int mode ) {
68
+ int prev = 0 ; // 이전 값
69
+ int dir = 0 ;
70
+ int y = s , x = 1 ;
71
+ // 시공의 돌풍으로 돌아올 때까지 반복
72
+ while (!(y == s && x == 0 )) {
73
+ int temp = board [y ][x ]; // 원래 값 기억
74
+ board [y ][x ] = prev ; // 다음 좌표를 이전 값으로 갱신
75
+ prev = temp ; // 이전 값을 원래 값으로 갱신
76
+ int ny = y + dy [dir ];
77
+ int nx = x + dx [dir ];
78
+ // 다음 좌표가 경계를 벗어난다면
79
+ if (!isValid (ny , nx )) {
80
+ // 방향 재설정
81
+ dir = (dir + mode + 4 ) % 4 ;
82
+ ny = y + dy [dir ];
83
+ nx = x + dx [dir ];
84
+ }
85
+ // 다음 좌표 결정
86
+ y = ny ;
87
+ x = nx ;
88
+ }
89
+ }
90
+
91
+ // 방 안의 먼지의 총합을 계산
92
+ private static int calculate () {
93
+ // 시공의 돌풍이 -1이므로 전처리
94
+ int sum = 2 ;
95
+ for (int i = 0 ; i < n ; i ++)
96
+ for (int j = 0 ; j < m ; j ++)
97
+ sum += board [i ][j ];
98
+ return sum ;
99
+ }
100
+
101
+ // 경계 체크
102
+ private static boolean isValid (int y , int x ) {
103
+ return 0 <= y && y < n && 0 <= x && x < m ;
104
+ }
105
+ }
0 commit comments