코딩테스트

[백준] 7576번: 토마토

시제이 2024. 2. 22. 10:19
728x90
반응형

 

그래프 탐색 문제이다.

 

 

 

 

 

 

처음 생각했던 접근방식

상하좌우로 토마토가 익기 때문에, BFS를 사용하여 문제를 해결해야겠다는 생각이 우선적으로 들었다. 그리고 다른 쉬운 그래프 문제와는

다르게 처음 익은 토마토가 여러개가 존재할 수 있기 때문에, 큐에 토마토 위치를 다 넣어주고 순회하면 되었다.

또한, 순회하면서 총 토마토 개수를 세며, 기존 상자에 들어갈 수 있는 토마토의 개수를 비교하여 조건에 맞게 -1, 0, 1을 출력할 수 있다.

 

그러나 구현하는데 있어서 순간 막혔던 부분은 "토마토가 여러개가 있을 경우 다 익는 데 최소로 걸리는 시간을 어떻게 구현할 것인가"였다.

처음 생각했던 방식은 단순하게 BFS안에서 각 날짜에 따라 세는 방법이었는데, 큐로 구현했기 때문에 각 익은 토마토에 인접한 다른 토마토들의 개수가 다르므로 몇개인지 따로 기록하는 매우 복잡한(?) 구현을 해야했다. 그래서 접근방식이 잘못되었다는 점을 인지하였다.

 

 

 

 

 

 

합당한 접근방식

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
#include <iostream>
#include <vector>
#include <queue>
 
using namespace std;
 
int x, y;
int box[1000][1000];
int countDays[1000][1000];
bool visited[1000][1000];
vector<pair<int,int>> tomatos;
 
bool check(int yq, int xq){
    if(yq<0 || yq>=|| xq<0 || xq>=x) return false;
    if(visited[yq][xq] == truereturn false;
    if(box[yq][xq] == -1 || box[yq][xq] == 1return false;
    return true;
}
int bfs(){
 
    int count = 0;
    queue<pair<int,int>> q;
    for(auto tomato: tomatos){
        q.push(tomato);
        visited[tomato.first][tomato.second] = true;
    }
    while(!q.empty()){
        int xq = q.front().second;
        int yq = q.front().first;
        q.pop();
        visited[yq][xq] = true;
        count++;
 
        if(check(yq,xq-1)){
            q.push(make_pair(yq,xq-1));
            visited[yq][xq-1= true;
            countDays[yq][xq-1= countDays[yq][xq] + 1;
        }
        if(check(yq,xq+1)){
            q.push(make_pair(yq,xq+1));
            visited[yq][xq+1= true;
            countDays[yq][xq+1= countDays[yq][xq] + 1;
        }
        if(check(yq-1,xq)){
            q.push(make_pair(yq-1,xq));
            visited[yq-1][xq] = true;
            countDays[yq-1][xq] = countDays[yq][xq] + 1;
        }
        if(check(yq+1,xq)){
            q.push(make_pair(yq+1,xq));
            visited[yq+1][xq] = true;
            countDays[yq+1][xq] = countDays[yq][xq] + 1;
        }
 
    }
    return count;
 
}
 
int main(){
 
    cin >> x >> y;
    int minus = 0;
    memset(visited, falsesizeof(visited));
    for(int i=0; i<y; i++){
        for(int j=0; j<x; j++){
            cin >> box[i][j];
            countDays[i][j] = box[i][j];
            if(box[i][j] == 1) tomatos.push_back(make_pair(i,j));
            if(box[i][j] == -1) minus++;
        }
    }
    if(bfs() != (x*y-minus)){
        cout << -1;
        return 0
    }
    int max = 0;
    for(int i=0; i<y; i++){
        for(int j=0; j<x; j++){
            if(countDays[i][j] > max){
                max = countDays[i][j];
            }
        }
    }
    cout << max-1;
 
    return 0;
}
 
 
cs

 

해결책은 새로운 2차원배열(countDays)을 두고 순회할 때마다 이전 칸의 countDays+1을 넣는것이다.

그렇게하면, 굳이 기존에 만들었던 알고리즘을 복잡하게 개조할 필요 없이 나중에 countDays의 최대값을 구하면

그것이 토마토가 다 익는데 걸리는 최소시간이기 때문이다. 다만, 1부터 시작했으므로 총 기간은 max-1이 된다.

 

countDays의 최대값이 다 익는데 걸리는 최소시간을 만족한다.

 

 

 

 

평소에 알고리즘 문제를 풀 때 기존 알고리즘에 간단한 변수만으로 복잡하게 구현하려는 좋지 않은 습관이 있다는 것을 인지했다.

쉽게 표시할 수 있도록 새로운 자료구조를 추가하고, 조금 더 논리적이고 직관적으로 프로그래밍하기 쉬운 방법을 찾아갈 수 있도록 더욱 노력해야겠다.   

 

 

 

 

반응형