ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • boj)18808 - 스티커 붙이기
    PS/boj 2020. 11. 27. 22:56
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    import java.io.*;
    import java.util.*;
     
    public class boj_18808 {
        static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer st;
        static int n, m, k, ans;
        static int[][] board;
        static int[] startPoint;
        static List<int[][]> stickers = new ArrayList<>();
     
        public static void main(String[] args) throws IOException {
            input();
            solve();
            printAns();
        }
     
        static void solve() {
            // 모든 스티커에 대해서 검사
            for (int[][] sticker : stickers) {
                // 스타트 가능한 부분 찾기, (0, 0) ~ (maxXSize, maxYSize)
                int[] canStartDotMax = findDot(sticker);
     
                // 가능한 부분인지 확인하기 -> 가능하다면 startPoint 에 시작하는 x, y 좌표 담음
                boolean possibleToStart = isPossibleToStart(canStartDotMax, sticker);
     
                if (possibleToStart) {
                    // 스티커 붙이기
                    attachSticker(sticker); // startPoint[] static 주의
                } else {
                    // 스티커 회전하기 90, 180, 270도
                    for (int turnCount = 1; turnCount <= 3; turnCount++) {
                        int[][] turnSticker = rotate(turnCount, sticker);
     
                        int[] dot = findDot(turnSticker);
                        if (isPossibleToStart(dot, turnSticker)) {
                            attachSticker(turnSticker); // startPoint[] static 주의
                            break// 이미 스티커를 붙였다면 다음 스티커로 넘어감
                        }
                    }
                }
            }
        }
     
        static int[][] rotate(int turnCount, int[][] sticker) {
            // do turn, turnCount 1 - 90, 2 - 180, 3 - 270 도
            int row = sticker.length;
            int col = sticker[0].length;
            int[][] turnSticker;
     
            // 회전시키기
            if (turnCount == 1) { // 90
                turnSticker = new int[col][row];
                for (int i = 0; i < col; i++) {
                    for (int j = 0; j < row; j++) {
                        turnSticker[i][j] = sticker[row-1-j][i];
                    }
                }
            } else if (turnCount == 2) { // 180
                turnSticker = new int[row][col];
                for (int i = 0; i < row; i++) {
                    for (int j = 0; j < col; j++) {
                        turnSticker[i][j] = sticker[row-1-i][col-1-j];
                    }
                }
            } else { // 270
                turnSticker = new int[col][row];
                for (int i = 0; i < col; i++) {
                    for (int j = 0; j < row; j++) {
                        turnSticker[i][j] = sticker[j][col-1-i];
                    }
                }
            }
            return turnSticker;
        }
     
        static void attachSticker(int[][] sticker) {
            int x = startPoint[0];
            int y = startPoint[1];
            int row = sticker.length;
            int col = sticker[0].length;
     
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    if (sticker[i][j] == 1) {
                        board[i + x][j + y] = sticker[i][j];
                    }
                }
            }
        }
     
        static boolean checkPoint(int x, int y, int[][] sticker) {
            int row = sticker.length;
            int col = sticker[0].length;
     
            boolean flag = true;
            all : for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    if (sticker[i][j] == 0continue;
                    if (board[i + x][j + y] == 1) { // 이미 스티커가 붙여져있으면
                        flag = false;
                        break all;
                    }
                }
            }
            return flag;
        }
     
        static boolean isPossibleToStart(int[] now, int[][] sticker) {
            int maxX = now[0];
            int maxY = now[1];
     
            if (maxX < 0 || maxY < 0return false;
     
            // 0 ~ maxX , 0 ~ maxY
            boolean flag = false;
            all : for (int startX = 0; startX <= maxX; startX++) {
                for (int startY = 0; startY <= maxY; startY++) {
     
                    // 시작포인트에서 스티커를 붙일 수 있는가 를 확인
                    if (checkPoint(startX, startY, sticker)) {
                        startPoint = new int[] { startX, startY };
                        flag = true;
                        break all;
                    }
                }
            }
            return flag;
        }
     
        static int[] findDot(int[][] sticker) {
            int xSize = sticker.length;
            int ySize = sticker[0].length;
     
            // find startDot
            int maxXSize = n - xSize;
            int maxYSize = m - ySize;
            return new int[] { maxXSize, maxYSize };
        }
     
        static void input() throws IOException {
            st = new StringTokenizer(br.readLine());
            n = Integer.parseInt(st.nextToken());
            m = Integer.parseInt(st.nextToken());
            k = Integer.parseInt(st.nextToken());
            board = new int[n][m];
     
            for (int i = 0; i < k; i++) {
                st = new StringTokenizer(br.readLine());
                int a = Integer.parseInt(st.nextToken());
                int b = Integer.parseInt(st.nextToken());
     
                int[][] sticker = new int[a][b];
     
                for (int j = 0; j < a; j++) {
                    st = new StringTokenizer(br.readLine());
                    for (int l = 0; l < b; l++) {
                        sticker[j][l] = Integer.parseInt(st.nextToken());
                    }
                }
     
                stickers.add(sticker);
            }
        }
     
        static void printAns() {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (board[i][j] == 1) ans++;
                }
            }
            System.out.println(ans);
        }
    }
    cs

     

    - 시뮬레이션

    - 어려움

     

    - 어제도 고민하고 오늘도 계속 붙잡아서 겨우 성공 

    - 접근 자체가 생각이 안나는건 아니고 생각한걸 코드로 짜내는 과정이 어려웠음

     

    1. 스티커를 list에 저장

    2. 스티커의 제일 끝을 기준으로 스티커를 붙일 수 있는 최대 시작 포인트의 x, y 좌표 저장  canStartDotMax

    3. 0~최대X, 0~최대Y 값을 기준으로 붙일 수 있는지 확인  isPossibleToStart 

    4. 가능 하다면 스티커 붙이기 attachSticker

    5. 불가능하다면 90, 180, 270도 순서로 회전 시킨후 위의 과정 반복 rotate

     

     

     

     


    www.acmicpc.net/problem/18808

    'PS > boj' 카테고리의 다른 글

    boj)10973 - 이전 순열  (0) 2020.11.30
    boj)10972 - 다음 순열  (0) 2020.11.30
    boj)15683 - 감시  (0) 2020.11.25
    boj)1182 - 부분수열의 합  (0) 2020.11.23
    boj)9663 - N-Queen  (0) 2020.11.19
킹수빈닷컴