Nick Dev

[코드트리] 2차원 바람(Java) 본문

코딩 테스트

[코드트리] 2차원 바람(Java)

Nick99 2024. 12. 28. 14:21
반응형

문제

문제 링크

https://www.codetree.ai/missions/2/problems/The-2D-wind-blows?&utm_source=clipboard&utm_medium=text

내 코드

import java.util.*;
import java.io.*;

public class Main {
    static int n;
    static int m;
    static int[][] grid;
    static int r1;
    static int c1;
    static int r2; 
    static int c2;

    public static void main(String[] args) throws IOException {
        // 여기에 코드를 작성해주세요.
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        int q = Integer.parseInt(st.nextToken());
        grid = new int[n][m];

        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < m; j++) grid[i][j] = Integer.parseInt(st.nextToken());
        }

        while (q-- > 0) {
            st = new StringTokenizer(br.readLine());
            r1 = Integer.parseInt(st.nextToken())-1;
            c1 = Integer.parseInt(st.nextToken())-1;
            r2 = Integer.parseInt(st.nextToken())-1;
            c2 = Integer.parseInt(st.nextToken())-1;

            blow();
        }

        for (int i = 0; i < n; i++) {
            for (int a : grid[i]) System.out.print(a + " ");
            System.out.println();
        }

    }

    public static void blow() {
        // 윗변
        int tmp1 = grid[r1][c2];
        for (int j = c2; j > c1; j--) {
            grid[r1][j] = grid[r1][j-1];
        } 

        // 오른쪽 변
        int tmp2 = grid[r2][c2];
        for (int i = r2-1; i > r1; i--) {
            grid[i+1][c2] = grid[i][c2];
        }
        grid[r1+1][c2] = tmp1;

        // 아랫변
        tmp1 = grid[r2][c1];
        for (int j = c1 + 1; j < c2; j++) {
            grid[r2][j-1] = grid[r2][j];
        }
        grid[r2][c2-1] = tmp2;

        // 왼쪽 변
        for (int i = r1+1; i < r2; i++) {
            grid[i-1][c1] = grid[i][c1];
        }
        grid[r2-1][c1] = tmp1;

        // 직사각형 영역 내의 숫자들 평균값으로 변경
        sideEffect();
    }

    public static void sideEffect() {
        // 동시에 일어나야 되서 깊은 복사 진행
        int[][] tmp = new int[n][m];
        for (int i = 0; i < n; i++) {
            tmp[i] = grid[i].clone();
        }

        for (int i = r1; i <= r2; i++) {
            for (int j = c1; j <= c2; j++) {
                calcAvg(tmp, i, j);
            }
        }
    }

    static int[] dxs = new int[]{1, 0, -1, 0};
    static int[] dys = new int[]{0, 1, 0, -1};

    public static void calcAvg(int[][] tmp, int x, int y) {
        int sum = tmp[x][y];
        int count = 1;
        for (int i = 0; i < 4; i++) {
            int nx = x + dxs[i];
            int ny = y + dys[i];
            if (0 <= nx && nx < n && 0 <= ny && ny < m) {
                count++;
                sum += tmp[nx][ny];
            }
        }
        grid[x][y] = sum / count;
    }
}

설명

blow()

  • 직사각형 경계에 있는 숫자들 시계 방향으로 돌린다
  • 그 후에 sideEffect() 라는 메서드 호출
    • 현재 좌표를 인접한 좌표들의 합의 평균으로 변환하는 메서드

sideEffect()

  • 각 좌표의 값 수정이 동시에 발생하는거라서 이전 좌표의 값 수정이 다음 좌표 값 수정할 때 반영되면 안된다

  • 그래서 초기에는 int[][] tmp = grid; 로 대입하고 grid[x][y] = sum / count; 로 grid의 값을 수정했더니 tmp[x][y] 접근해도 grid[x][y]의 값이 반영되어있었다.

  • 난 배열의 내용을 대입할 생각으로 했는데 사실 얕은 복사 를 했던 것이다.

  • 즉, tmp, grid 두 변수 모두 물리적으로 같은 2차원 배열을 바라보고 있는 것이다.

  • 그래서 진짜 원소만 싸악 복사하려면

      int[][] tmp = new int[n][m];
      for (int i = 0; i < n; i++) {
          tmp[i] = grid[i].clone();
      }
    • 이렇게 clone()을 통해서 깊은 복사를 해줘야 한다.
    • 이렇게 해야 tmpgrid는 내용만 같고 물리적으로 아예 다른 2개의 배열이 되는 것
  • 각 좌표에 대해서 calcAvg() 호출

    • 각 좌표의 상하좌우를 살표보고 평균값 구하는 메서드
반응형