입력 | 출력 |
6 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 |
8 |
6 4 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 |
-1 |
6 4 1 -1 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 -1 1 |
6 |
5 5 -1 1 0 0 0 0 -1 -1 -1 0 0 -1 -1 -1 0 0 -1 -1 -1 0 0 0 0 0 0 |
14 |
2 2 1 -1 -1 1 |
0 |
✍문제 풀이
✔ 토마토가 익는 과정은 아래와 같다.
✔ 처음 시작이 '1'일 때, 닿아 있는 면'0'이면 '1'로 변합니다. 따라서 BFS로 풀어줍니다.
✔ 방법
① 초기에 주어지는 map을 입력받을 때, queue에 '1'인 칸 좌표를 저장한다.
> 이유는 1인 칸이 여러 개일 때, 동시에 일수를 계산하기 위해서이다.
② bfs( )를 실행한다.
② -1. queue가 empty( )가 아닐 때까지 반복한다.
② -2. x, y 좌표 값을 저장하고, 방문 체크를 해준다. x, y 좌표 값을 변수에 저장했다면 queue는 지워준다.'-1'이면 무시한다. '0'이면 '1'로 바꾼 후에 일수를 더해준다.
② -3. 상하좌우 이동이 가능한지 체크하기 위해 반복한다.
② -3-(1). 토마토 상자 범위를 벗어나면 무시한다. 또한 상자 안의 원소가 '-1'(토마토가 없으면)이면 무시한다.
② -3-(2). 방문하지 않은 곳이고, 상자에 토마토가 있으면('0')이면
queue에 좌표를 저장하고, 방문체크를 하고, 일수를 더해준다.
③ bfs 탐색 후, '0'인 칸이 하나 이상이면 -1을 return한다.
'0'인 칸이 없으면 일수를 return한다.
🌱 정답코드
+) 처음에 짜고 틀린 코드
① '1'인 칸을 찾는다
② '-1'이면 무시한다. '0'이면 '1'로 바꾼 후에 일수를 더해준다.
③ bfs 탐색 후, '0'인 칸이 하나 이상이면 -1을 return한다.
④ '0'이 없다면 일수 -1인 값을 출력한다.
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int N, M;
int map[1001][1001];
bool check[1001][1001];
// 상하좌우 이동
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int day; // 토마토가 익은 일수 체크
void bfs(int x, int y){
queue<pair<int, int>> q;
q.push({x, y});
check[x][y] = true; // 방문 체크
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
q.pop();
// 상하좌우 토마토 익는 것 체크
for(int i = 0; i < 4; i++){
int nx = x + dx[i];
int ny = y + dy[i];
// map 범위 벗어나면 무시
if(nx < 0 || ny < 0 || nx > N || ny > M) continue;
// ********
// 범위는 if(nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
// 토마토가 없으면 무시
if(map[nx][ny] == -1) continue;
// 익지 않은 토마토가 있으면 익혀주기
if(map[nx][ny] == 0){
map[nx][ny] = map[x][y] + 1;
q.push({nx, ny});
check[nx][ny] = true;
}
}
}
}
int main() {
int answer = 0;
cin >> M >> N;
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
cin >> map[i][j];
}
}
int oneCheck = 0;
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(map[i][j] == 1){
bfs(i, j);
oneCheck++;
}
}
}
int max = 0, zeroCheck = 0;
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(map[i][j] == 0) zeroCheck++;
if(max < map[i][j]) max = map[i][j];
}
}
if(zeroCheck >= 1) answer = -1;
else if(oneCheck > 1 && zeroCheck == 0){
answer = (max / oneCheck) + 1;
}
else answer = max - 1;
cout << answer;
return 0;
}
6 4 1 -1 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 -1 1 |
else if(oneCheck > 1 && zeroCheck == 0){ answer = (max / oneCheck) + 1; } 위 코드로 어떻게든 정답 코드로 만들었는데, |
'1'이 여러 개고, '0'을 '1'로 만들 때는 일수를 체크하지 못함.. |
결과는 5여야 하지만 가 출력됨..ㅎ |
틀린 코드인줄 알면서 한 번 제출해봄 ㅎ..ㅎ
✔ 1인 칸이 여러 개일 때, 동시에 확인하려면 queue에 1이 든 공간의 좌표 값을 저장하고,
bfs를 돌릴 때, 각 좌표를 하나씩 꺼내서 확인해주면 된다.
내가 처음 짰던 코드는 1이 여러 개일 때는 생각하지 못하고 짠 코드이다.
풀이 참고
하루가 지날 때마다 익은 토마토들은 큐에 넣어주고 |
|
1. 창고를 입력 받는데 1이면 덱에 넣고, -1이면 noTomato를 증가시킵니다. |
|
1. 토마토가 익은 점들을 큐에 넣어준다. (동시 다발적으로 일어나기 때문에 큐를 사용한 BFS) |
|
|
음.. 사실 다른 분의 문제 풀이 설명을 다 이해하지 못했다...
그러나 4번 블로그 분의 풀이가 많은 도움이 되었다.
입력받을 때, '1'이 곳의 좌표값을 queue에 넣는다.
이후, bfs( ) 함수를 실행할 때, 1이었던 공간을 번갈아가며 순차적으로 실행하니까 정확한 답이 나온다.
'OLD_알고리즘 > Baekjoon' 카테고리의 다른 글
백준 ] 2606번 바이러스 (0) | 2021.03.29 |
---|---|
백준] 1697 : 숨바꼭질 (0) | 2021.03.29 |
백준] 2178 : 미로 탐색 (0) | 2021.03.25 |
백준] 2667 : 단지번호붙이기 (0) | 2021.03.24 |
백준 ] 1260번 DFS와 BFS (0) | 2021.03.24 |
댓글