길민호(ethan.mino)
코딩수첩
길민호(ethan.mino)
전체 방문자
오늘
어제
  • 분류 전체보기 (215)
    • Computer Science (0)
    • Web (6)
      • CSS (0)
      • HTML (0)
    • Node.js (0)
    • Javascript (2)
    • Java (46)
      • Spring (27)
      • Jsp (0)
    • C\C++ (2)
    • Programming (0)
    • AI (0)
    • Database (7)
    • Git (5)
    • Algorithm (119)
      • Stack (0)
      • Queue (0)
      • Linked List (0)
      • Sort (0)
      • Simulation (27)
      • Recursion (0)
      • Backtracking (4)
      • Two Pointer (3)
      • Dynamic Programming (19)
      • Greedy (10)
      • Graph (3)
      • Dijkstra (1)
      • BFS\DFS (8)
      • Floyd (1)
      • MST (4)
      • Tree (4)
      • Binary Search (8)
      • Binary Search Tree (4)
    • IntelliJ (4)
    • Vscode (0)
    • Operating System (0)
    • 후기 (3)
    • 성장일지 (13)
    • 스터디 (7)
    • 설치 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ㅡ

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
길민호(ethan.mino)

코딩수첩

Algorithm/Simulation

[백준 18808번] 스티커 붙이기 (C/C++)

2022. 3. 16. 01:52

https://www.acmicpc.net/problem/18808

 

18808번: 스티커 붙이기

혜윤이는 최근에 다양한 대회를 참여하면서 노트북에 붙일 수 있는 스티커들을 많이 받았다. 스티커는 아래와 같이 사각 모눈종이 위에 인쇄되어 있으며, 스티커의 각 칸은 상하좌우로 모두 연

www.acmicpc.net


전체 알고리즘의 기본 틀은 아래와 같습니다.

  1. 스티커의 각 좌표를 구한다. 
  2. 노트북에 붙여본다.
  3. 실패한다면 각 좌표를 90° 시킨다. 2번 부터 다시 진행한다. (단, 360° 회전시킨 경우, 더이상 노트북에 붙여보지 않는다.)

아래는 각 좌표를 90° 회전시키는 함수입니다. 

⚠️ 주의할 점은 이후에 또 다시 각 좌표를 90° 회전시킬 수 있기 때문에 n과 m을 교환해주어야 한다는 것입니다.  

void rotate(vector<pair<int, int>>& pos, int* n, int* m){ 
    for(int i = 0; i < pos.size(); i++){
        int nx = pos[i].y; int ny = (*n - 1) - pos[i].x;
        pos[i].x = nx; pos[i].y = ny;
    }

    int temp = *n; *n = *m; *m = temp;
}

 

다음으로 노트북에 스티커를 붙이는 함수입니다. 

스티커를 붙이는 기준 좌표를 하나씩 이동시켜가면서, 스티커를 붙일 수 있는지 확인하고, 붙일 수 있다면 해당 좌표들을 1로 표시하고 True를 반환합니다. 모든 기준 좌표를 확인해도 스티커를 붙일 수 없다면, False를 반환합니다.

bool attach(vector<pair<int, int>> pos){
    bool flag = false;
    for(int i = 0; i < n; i++){ // 기준 좌표는 {i, j}, 기준 좌표를 이동시키면서 스티커를 붙여봄
        for(int j = 0; j < m; j++){
            flag = true;    // 스티커를 붙일 수 있는지를 나타내는 flag
            for(auto c : pos){
                // 기준 좌표를 (0, 0)으로 잡았을 때 각 좌표의 새로운 좌표
                int nx = i + c.x; int ny = j + c.y;   

                // 이미 스티커가 붙어있거나, 노트북의 범위를 벗어나는 경우 flag를 false로 설정
                if(notebook[nx][ny] == 1 || nx < 0 || ny < 0 || nx >= n || ny >= m) 
                    flag = false;   
            }

            if(flag){   // 노트북에 스티커를 붙일 수 있다면
                for(auto c : pos){  
                    int nx = i + c.x; int ny = j + c.y;
                    notebook[nx][ny] = 1;   // 스티커를 붙임
                }
                return true;
            }
        }
    }
    return false;
}

 

 

아래는 전체 코드입니다.

#include <bits/stdc++.h>
using namespace std;

#define x first
#define y second

int notebook[40][40];   // 스티커를 붙일 노트북
int n, m, k;

void rotate(vector<pair<int, int>>& pos, int* n, int* m){ 
    for(int i = 0; i < pos.size(); i++){
        int nx = pos[i].y; int ny = (*n - 1) - pos[i].x;
        pos[i].x = nx; pos[i].y = ny;
    }

    int temp = *n; *n = *m; *m = temp;
}

bool attach(vector<pair<int, int>> pos){
    bool flag = false;
    for(int i = 0; i < n; i++){ // 기준 좌표는 {i, j}, 기준 좌표를 이동시키면서 스티커를 붙여봄
        for(int j = 0; j < m; j++){
            flag = true;    // 스티커를 붙일 수 있는지를 나타내는 flag
            for(auto c : pos){
                // 기준 좌표를 (0, 0)으로 잡았을 때 각 좌표의 새로운 좌표
                int nx = i + c.x; int ny = j + c.y;   

                // 이미 스티커가 붙어있거나, 노트북의 범위를 벗어나는 경우 flag를 false로 설정
                if(notebook[nx][ny] == 1 || nx < 0 || ny < 0 || nx >= n || ny >= m) 
                    flag = false;   
            }

            if(flag){   // 노트북에 스티커를 붙일 수 있다면
                for(auto c : pos){  
                    int nx = i + c.x; int ny = j + c.y;
                    notebook[nx][ny] = 1;   // 스티커를 붙임
                }
                return true;
            }
        }
    }
    return false;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m >> k;

    while(k--){ // 스티커 개수만큼 반복
        int tn, tm; cin >> tn >> tm;    // 스티커의 크기 입력 받음
        int board[10][10];  

        for(int i = 0; i < tn; i++)
            for(int j = 0; j < tm; j++)
                cin >> board[i][j]; // 스티커 입력 받음

        vector<pair<int, int>> pos;
        for(int i = 0; i < tn; i++)
            for(int j = 0; j < tm; j++)
                if(board[i][j] == 1) pos.push_back({i, j}); // 스티커의 각 좌표 push

        for(int i = 0; i < 4; i++){
            bool success = attach(pos); // 노트북에 스티커를 붙임
            if(success) break;  // 붙이기에 성공한 경우, 각 좌표를 회전시키지 않고 break
            else rotate(pos, &tn, &tm); // 붙이기에 실패한 경우, 각 좌표를 회전시킴
        }
    }

    int ans = 0;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            if(notebook[i][j] == 1) ans++; // 스티커가 붙은 칸 수 count

    cout << ans << "\n";
}

 

'Algorithm > Simulation' 카테고리의 다른 글

[백준 11559번] Puyo Puyo (C/C++)  (0) 2022.03.17
[백준 15686번] 치킨 배달 (C/C++)  (0) 2022.03.17
[백준 12100번] 2048 (easy) (C/C++)  (0) 2022.03.17
[백준 14888번] 연산자 끼워넣기 (C/C++)  (0) 2022.03.16
[백준 13335번] 트럭 (C/C++)  (0) 2022.03.16
    'Algorithm/Simulation' 카테고리의 다른 글
    • [백준 15686번] 치킨 배달 (C/C++)
    • [백준 12100번] 2048 (easy) (C/C++)
    • [백준 14888번] 연산자 끼워넣기 (C/C++)
    • [백준 13335번] 트럭 (C/C++)
    길민호(ethan.mino)
    길민호(ethan.mino)
    💻 호기심 많은 서버 개발자 길민호입니다.

    티스토리툴바