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

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100, 1 ≤ H ≤ 100 이다. 둘째 줄부터는 가장 밑의 상자부터 가장 위의 상자까지에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 하나의 상자에 담긴 토마토의 정보가 주어진다. 각 줄에는 상자 가로줄에 들어있는 토마

www.acmicpc.net

7576번 문제와 거의 똑같은 문제인데 범위가 조금 더 적고 대신에 상자가 3차원이다.

처음에 똑같은 상자가 h만큼 있는걸로 문제를 오해해서 잘못 풀었었다...;;

7576번 문제에서 3차원으로만 바꿔주면 되지만 나는 c++에 아직 익숙하지 않아서 조금 어려움을 겪었다ㅠㅠ

 

먼저 큐에 저장 하는 방식

2차원에서는 x와 y좌표만 넣어주면 되므로 pair를 사용하였지만 이 문제에서는 z좌표 까지 함께 넣어야한다.

처음에는 tuple을 사용하려 했지만 값을 받아오는 방법이 불편해서 다들 pair를  이중으로 쓴다길래 따라했다..

 

queue<pair<pair<int,int>int>> q;

 

이런식으로 pair를 중첩해서 넣어줬다. (x, y) 가 먼저 pair 가 되고, (x, y) 가 다시 z와 pair가 된다.

이렇게 pair만 3차원 방식에 맞게 구현해주면 나머지는 2차원 토마토와 거의 똑같다.

 

 

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
#include <cstdio>
#include <queue>
using namespace std;
int n,m,h;
int box[100][100][100];
int day[100][100][100];
int dx[] = {0,0,1,-1,0,0};
int dy[] = {1,-1,0,0,0,0};
int dz[] = {0,0,0,0,1,-1};
 
 
int main() {
 
    scanf("%d %d %d"&m, &n, &h);
    queue<pair<pair<int,int>,int> > q;
 
 
    for(int k=0; k<h; k++) {
        for(int i=0; i<n; i++) {
            for(int j=0; j<m; j++) {
 
                scanf("%d"&box[i][j][k]);
                day[i][j][k] = -1;
                //익은 토마토인 경우 큐에 넣는다.
                if(box[i][j][k] == 1) {
                    q.push(make_pair(make_pair(i,j),k));
                    day[i][j][k] = 0;
                }
             
            }
        }
    }
  
 
    while(!q.empty()) {
        int x = q.front().first.first;
        int y = q.front().first.second;
        int z = q.front().second;
        q.pop();
 
        for(int i=0; i<6; i++) {
            int nx = x+dx[i];
            int ny = y+dy[i];
            int nz = z+dz[i];
            
            //범위 체크
            if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
            if(nz < 0 || nz >= h) continue;
 
            //안익은 토마토 && 아직 방문 안함
            if(box[nx][ny][nz] == 0 && day[nx][ny][nz] == -1) {
                q.push(make_pair(make_pair(nx,ny),nz));
                day[nx][ny][nz] = day[x][y][z] + 1;
            }
        }
 
    }
 
 
    int ans = 0;
    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            for(int k=0; k<h; k++) {
                if(box[i][j][k] == 0 && day[i][j][k] == -1) {
                    ans = -1;
                    break;
                }
 
                if(ans < day[i][j][k])
                    ans = day[i][j][k];
            }
            if(ans == -1break;
            
        }
        if(ans == -1break;
    }
 
    printf("%d", ans);
 
    return 0;
}
Colored by Color Scripter
 

'BOJ' 카테고리의 다른 글

[BOJ] 14501. 퇴사  (0) 2019.06.27
[BOJ] 1697. 숨바꼭질  (0) 2019.06.27
[BOJ] 7576. 토마토  (0) 2019.06.27
[BOJ] 11724. 연결 요소의 개수  (0) 2019.06.27
[BOJ] 2178. 미로 탐색  (0) 2019.06.25

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

 

7576번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 상자에 담긴 토마토의 정보가 주어진다. 하나의 줄에는 상자 가로줄에 들어있는 토마토의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마

www.acmicpc.net

이 문제는 전형적인 bfs 문제이다.

상자에 있는 토마토가 상하좌우로 하루에 하나씩 익어가는데 모든 토마토가 익는데 걸리는 최소 일수를 구해야 하므로 bfs를 사용하면 된다.

기존에 익어있는 토마토로부터 익으므로 입력받을 때 익은 토마토인 경우 바로 큐에 넣어준다.

상하좌우를 탐색하며 방문하지 않은 토마토에 방문하여 소요 날짜를 저장한다.

 

 

탐색이 끝난 이후에는 문제의 조건에 따라 토마토가 모두 익지는 못하는 상황이라면 -1을 출력하기 위해서

안 익은 토마토인데 방문하지 않은 토마토를 찾는다. 혹시 존재한다면 ans는 -1 값을 가지고 그렇지 않은 경우에는

가장 마지막 토마토가 익은 날짜가 저장된다.

 

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
#include <cstdio>
#include <queue>
using namespace std;
int n,m;
int box[1000][1000];
int day[1000][1000];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
 
 
int main() {
 
    scanf("%d %d"&m, &n);
    queue<pair<int,int> > q;
 
    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            scanf("%d"&box[i][j]);
 
            //익는데 걸리는 날짜를 저장할 배열 -1로 초기화
            day[i][j] = -1;
 
            //익은 토마토인 경우 큐에 넣는다.
            if(box[i][j] == 1) {
                q.push(make_pair(i,j));
                day[i][j] = 0;
            }
        }
    }
 
 
    //bfs
    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];
 
            //범위 체크
            if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
 
            //안익은 토마토 && 아직 방문 안함
            if(box[nx][ny] == 0 && day[nx][ny] == -1) {
                q.push(make_pair(nx,ny));
 
                //소요 일수를 저장 (이전 칸보다 하루 증가)
                day[nx][ny] = day[x][y] + 1;
            }
        }
 
    }
 
 
    //탐색 종료 후에 안익은 토마토가 있는지를 검사 
    int ans = 0;
    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
 
            //안 익은 토마토가 있는데 방문하지 않았다.
            if(box[i][j] == 0 && day[i][j] == -1) {
                ans = -1;
                break;
            }
 
 
            //가장 마지막에 익은 토마토의 날짜를 구해야하므로
            //최댓값을 ans에 저장한다. 
            if(ans < day[i][j])
                ans = day[i][j];
        }
        //위의 반복문에서 안익은 토마토가 있는 경우 빠져나와서 break
        if(ans == -1break;
    }
 
    printf("%d", ans);
 
    return 0;
}
Colored by Color Scripter
 

'BOJ' 카테고리의 다른 글

[BOJ] 1697. 숨바꼭질  (0) 2019.06.27
[BOJ] 7569. 토마토 (3차원)  (0) 2019.06.27
[BOJ] 11724. 연결 요소의 개수  (0) 2019.06.27
[BOJ] 2178. 미로 탐색  (0) 2019.06.25
[BOJ] 4963. 섬의 개수  (0) 2019.06.25

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

 

7576번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 상자에 담긴 토마토의 정보가 주어진다. 하나의 줄에는 상자 가로줄에 들어있는 토마토의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마

www.acmicpc.net

문제

철수의 토마토 농장에서는 토마토를 보관하는 큰 창고를 가지고 있다. 토마토는 아래의 그림과 같이 격자 모양 상자의 칸에 하나씩 넣어서 창고에 보관한다. 

창고에 보관되는 토마토들 중에는 잘 익은 것도 있지만, 아직 익지 않은 토마토들도 있을 수 있다. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. 하나의 토마토의 인접한 곳은 왼쪽, 오른쪽, 앞, 뒤 네 방향에 있는 토마토를 의미한다. 대각선 방향에 있는 토마토들에게는 영향을 주지 못하며, 토마토가 혼자 저절로 익는 경우는 없다고 가정한다. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지, 그 최소 일수를 알고 싶어 한다.

토마토를 창고에 보관하는 격자모양의 상자들의 크기와 익은 토마토들과 익지 않은 토마토들의 정보가 주어졌을 때, 며칠이 지나면 토마토들이 모두 익는지, 그 최소 일수를 구하는 프로그램을 작성하라. 단, 상자의 일부 칸에는 토마토가 들어있지 않을 수도 있다.

 

입력

상자의 크기를 나타내는 두 정수 M, N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다.

단, 2 ≤ M,N ≤ 1,000이다.

정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다.

만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

 

풀이

  1. 상자의 토마토가 인접한 네 방향에 영향을 주며, 다 익게 되는 최소 일수를 구하는 문제 -> BFS 문제다.
  2. 토마토 정보를 입력받을 때 1 (익은 토마토)이면 큐에 넣어준다. (익은 토마토로부터 익기 시작하므로)
  3. BFS 실행
    1. 아직 방문하지 않았고, 익지 않은 토마토가 있는 곳을 방문한다.
    2. day 배열에 해당 칸이 익는데 걸린 일수를 넣는다.
    3. 토마토가 모두 익은 날을 구해야 하므로 max값에 day배열의 최댓값을 넣어준다.
  4. 탐색이 모두 끝났는데 아직 익지 않은 토마토가 있고 그 토마토에 방문하지 않았다면 -1을 출력하고 종료.
  5. 아니면 max값을 출력.
import java.util.*;
import java.io.*

public class Main {
	
	static class Pair {
		int x;
		int y;
		Pair(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
	
	static int dx[] = {0, 0, 1, -1};
	static int dy[] = {1, -1, 0, 0};
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int m = Integer.parseInt(st.nextToken());
		int n = Integer.parseInt(st.nextToken());
		
		int box[][] = new int[n][m];
		boolean check[][] = new boolean[n][m];
		Queue&ltTomato> q = new LinkedList&ltTomato>();
		
		for(int i=0; i<n; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0; j<m; j++) {
				box[i][j] = Integer.parseInt(st.nextToken());
				if(box[i][j] == 1) {
					check[i][j] = true;
					q.add(new Pair(i,j));
				}
			}
		}
		
		int day[][] = new int[n][m];
		int max = 0;
		while(!q.isEmpty()) {
			Pair p = q.remove();
			int x = p.x;
			int y = p.y;
			for(int i=0; i<4; i++) {
				int nx = x + dx[i];
				int ny = y + dy[i];
				if(nx >=0 && ny >=0 && nx &ltn && ny &lt m)
					if(box[nx][ny] == 0 && check[nx][ny] == false) {
						check[nx][ny] = true;
						day[nx][ny] = day[x][y] +1;
						q.add(new Pair(nx,ny));
						if(max &lt day[nx][ny]) max = day[nx][ny];
					}
			}
		}

		for(int i=0; i<n; i++) {
			for(int j=0; j<m; j++) {
				if(box[i][j] == 0 && check[i][j] == false){
					System.out.println(-1);
					return;
				}
			}
		}
		System.out.println(max);
	}
}

'BOJ' 카테고리의 다른 글

[BOJ] 2606. 바이러스  (0) 2019.05.01
[BOJ] 4963. 섬의 개수  (0) 2019.05.01
[BOJ] 7569. 토마토 (3차원)  (0) 2019.04.30
[BOJ] 11724. 연결 요소의 개수  (0) 2019.04.29
[BOJ] 2309. 일곱 난쟁이  (0) 2019.04.29

+ Recent posts