|
| 1 | +import java.util.*; |
| 2 | + |
| 3 | +public class Main { |
| 4 | + static int n; |
| 5 | + static int m; |
| 6 | + static int k; |
| 7 | + |
| 8 | + static int[][] arr; |
| 9 | + |
| 10 | + static int min = Integer.MAX_VALUE; |
| 11 | + |
| 12 | + static Op[] ops; |
| 13 | + static boolean[] visited; |
| 14 | + static int[] selected; |
| 15 | + |
| 16 | + static class Op { |
| 17 | + int r, c, s; |
| 18 | + |
| 19 | + public Op(int r, int c, int s) { |
| 20 | + this.r = r; |
| 21 | + this.c = c; |
| 22 | + this.s = s; |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + public static void main(String[] args) { |
| 27 | + |
| 28 | + Scanner sc = new Scanner(System.in); |
| 29 | + |
| 30 | + n = sc.nextInt(); |
| 31 | + m = sc.nextInt(); |
| 32 | + k = sc.nextInt(); |
| 33 | + |
| 34 | + arr = new int[n][m]; |
| 35 | + ops = new Op[k]; |
| 36 | + visited = new boolean[k]; |
| 37 | + selected = new int[k]; |
| 38 | + |
| 39 | + for (int i = 0; i < n; i++) { |
| 40 | + for (int j = 0; j < m; j++) { |
| 41 | + arr[i][j] = sc.nextInt(); |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + for (int i = 0; i < k; i++) { |
| 46 | + int r = sc.nextInt(); |
| 47 | + int c = sc.nextInt(); |
| 48 | + int s = sc.nextInt(); |
| 49 | + ops[i] = new Op(r, c, s); |
| 50 | + } |
| 51 | + |
| 52 | + solve(); |
| 53 | + |
| 54 | + } |
| 55 | + |
| 56 | + public static void solve() { |
| 57 | + dfs(0); |
| 58 | + System.out.println(min); |
| 59 | + } |
| 60 | + |
| 61 | + public static void dfs(int depth) { |
| 62 | + if (depth == k) { |
| 63 | + int[][] copy = new int[n][m]; |
| 64 | + for (int i = 0; i < n; i++) { |
| 65 | + for (int j = 0; j < m; j++) { |
| 66 | + copy[i][j] = arr[i][j]; |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + for (int i = 0; i < k; i++) { |
| 71 | + rotate(copy, ops[selected[i]]); |
| 72 | + } |
| 73 | + |
| 74 | + for (int i = 0; i < n; i++) { |
| 75 | + int sum = 0; |
| 76 | + for (int j = 0; j < m; j++) { |
| 77 | + sum += copy[i][j]; |
| 78 | + } |
| 79 | + min = Math.min(min, sum); |
| 80 | + } |
| 81 | + |
| 82 | + return; |
| 83 | + } |
| 84 | + |
| 85 | + for (int i = 0; i < k; i++) { |
| 86 | + if (visited[i]) |
| 87 | + continue; |
| 88 | + visited[i] = true; |
| 89 | + selected[depth] = i; |
| 90 | + dfs(depth + 1); |
| 91 | + visited[i] = false; |
| 92 | + |
| 93 | + } |
| 94 | + |
| 95 | + } |
| 96 | + |
| 97 | + public static void rotate(int[][] arr, Op op) { |
| 98 | + int r = op.r - 1; |
| 99 | + int c = op.c - 1; |
| 100 | + int s = op.s; |
| 101 | + |
| 102 | + // 중요: 가장 바깥쪽(s)만 돌리면 안 되고, 안쪽 사각형들도 같이 돌려야 합니다. |
| 103 | + for (int gap = 1; gap <= s; gap++) { |
| 104 | + // s 대신 gap을 사용해야 합니다. |
| 105 | + // 1. 왼쪽 위 값 저장 |
| 106 | + int temp = arr[r - gap][c - gap]; |
| 107 | + |
| 108 | + // 2. 왼쪽 줄 이동 (아래 -> 위) : OK (잘하셨어요) |
| 109 | + for (int i = r - gap; i < r + gap; i++) { |
| 110 | + arr[i][c - gap] = arr[i + 1][c - gap]; |
| 111 | + } |
| 112 | + |
| 113 | + // 3. 아래 줄 이동 (오른쪽 -> 왼쪽) : OK (잘하셨어요) |
| 114 | + for (int i = c - gap; i < c + gap; i++) { |
| 115 | + arr[r + gap][i] = arr[r + gap][i + 1]; |
| 116 | + } |
| 117 | + |
| 118 | + // 4. 오른쪽 줄 이동 (위 -> 아래) : 수정 필요 |
| 119 | + // 현재 코드처럼 i++으로 돌면 위쪽 값이 계속 덮어씌워져서 망가집니다. |
| 120 | + // 아래쪽부터 채워야 하므로 i-- (역순)으로 돌아야 합니다. |
| 121 | + for (int i = r + gap; i > r - gap; i--) { |
| 122 | + arr[i][c + gap] = arr[i - 1][c + gap]; |
| 123 | + } |
| 124 | + |
| 125 | + // 5. 위쪽 줄 이동 (왼쪽 -> 오른쪽) : 수정 필요 |
| 126 | + // 마찬가지로 오른쪽부터 채워야 하므로 i-- (역순)으로 돌아야 합니다. |
| 127 | + for (int i = c + gap; i > c - gap; i--) { |
| 128 | + arr[r - gap][i] = arr[r - gap][i - 1]; |
| 129 | + } |
| 130 | + |
| 131 | + // 6. 저장해둔 temp 값 넣기 |
| 132 | + arr[r - gap][c - gap + 1] = temp; |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | +} |
0 commit comments