알고리즘

[BOJ] 1780 종이의 개수

졔졔311 2023. 5. 31. 20:36
728x90
반응형

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

 

1780번: 종이의 개수

N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1 중 하나가 저장되어 있다. 우리는 이 행렬을 다음과 같은 규칙에 따라 적절한 크기로 자르려고 한다. 만약 종이가 모두 같은 수

www.acmicpc.net

---------------------------------------------------핵심 알고리즘--------------------------------------------

 

recursive + divide&conquer

 

---------------------------------------------------풀이----------------------------------------------------

 

종이의 맨 왼쪽위 좌표 (sx,sy), 맨 오른쪽아래 좌표 (ex, ey)를 저장하는 structure node를 만들어 사용하였다.

큐에 아직 완료되지 않은(한 가지 숫자로 이루어지지 않은/이루어졌는지 체크하지 않은) 종이 위치 node를 저장해 큐가 비어있을 때까지  cut_paper()를 반복한다.

 

cut_paper()에서는 큐의 front를 cur로 받아오고,

cur이 전부 같은 숫자로 이루어졌는지 find_number()를 사용해 저장한다.

find_number()는 같은 숫자로 이루어졌으면 그 숫자를, 아니면 999를 리턴한다.

cur이 전부 같은 숫자로 이루어진 것이 아니라면, 9개로 잘라 다시 큐에 저장한다.

#define FASTIO ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <limits.h>

using namespace std;

int map[3000][3000] = {0, };

typedef struct{
    int sx, sy, ex, ey;
}node;

// 종이의 시작점, 끝점
int minus_one = 0, zero = 0, plus_one = 0;
queue<node> not_found;

int find_number(int sx, int sy, int ex, int ey){
    int num = map[sx][sy];
    for(int i = sx; i <= ex; i++){
        for(int j = sy; j <= ey; j++){
            if(map[i][j] != num){
                return 999;
            }
        }
    }
    return num;
}

void cut_paper(){
    node cur = not_found.front();
    // 전부 같은 숫자로 이루어졌다면 종료
    int num = find_number(cur.sx, cur.sy, cur.ex, cur.ey);
    if(num == -1){
        minus_one++;
    }
    else if(num == 0){
        zero++;
    }
    else if(num == 1){
        plus_one++;
    }
    // 9개의 조각으로 나누어 not_found에 삽입하기
    else{
        int size = (cur.ex - cur.sx + 1) / 3;
        for(int i = 0; i < 3; i++){
            for(int j = 0; j < 3; j++){
                node tmp;
                tmp.sx = cur.sx+i*size;
                tmp.sy = cur.sy+j*size;
                tmp.ex = cur.sx+i*size+size-1;
                tmp.ey = cur.sy+j*size+size-1;
                not_found.push(tmp);
            }
        }
    }
}

// 종이가 모두 같은 수로 되어 있다면 그대로 사용.
// 아니면 종이를 같은 크기의 종이 9개로 자르고 반복.
int main(void){
    FASTIO;
    int N;
    cin >> N;   // 3^K 형태.
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            cin >> map[i][j];
        }
    }

    node tmp;
    tmp.sx = 0; tmp.sy = 0; tmp.ex = N-1; tmp.ey = N-1;
    not_found.push(tmp);
    // not_found가 없어질 때까지 반복
    while(!not_found.empty()){
        cut_paper();
        not_found.pop();
    }

    cout << minus_one << "\n" << zero << "\n" << plus_one << "\n";
    return 0;
}

 

---------------------------------------------------후기----------------------------------------------------

 

제출하면 1%에서 out of bounds 오류가 계속 나서 무슨 문젠가 했더니

map[][]의 크기를 1000x1000으로 설정해 놓은게 문제였다.

3^7은 2187이므로 그 이상으로 해야하는데...네 자리 숫자길래 1000으로 설정해버린 것 같다. :(

728x90
반응형

'알고리즘' 카테고리의 다른 글

[BOJ] 2630 색종이 만들기  (2) 2023.06.01
[BOJ] 1931 회의실 배정  (0) 2023.06.01
[BOJ] 1764 듣보잡  (0) 2023.05.31
[BOJ] 1697 숨바꼭질  (0) 2023.05.31
[BOJ] 1676 팩토리얼 0의 개수  (0) 2023.05.31