1. 문제

1) 문제 링크

    : www.acmicpc.net/problem/7569

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

 

2) 설명

토마토가 다 익는 데 걸리는 시간(처음부터 모두 익어있었다면 0, 다 익을 수 없는 상황이면 -1)을 구하는 문제.

안 익은 토마토 = 0

토마토가 없는 칸 = -1

익은 토마토 = 1

로 주어지고 익은 토마토 주변의 안 익은 토마토들이 익는다.

 

 

2. 풀이

1) 알고리즘

   : BFS

 

2) 풀이 설명

예전에 풀었던 문제지만 다시 한번 풀어봤다.

 

전형적인 BFS문제다.

 

토마토 익을 때까지 큐에 넣다 뺐다 하면서 계속 돌리면 된다.

 

bfs에서 자주 사용하는 visited 배열(방문 확인을 위한)을 사용하지 않은 이유는 0인 칸을 방문하게 되면 (이전 칸 + 1) 값으로 계속 업데이트 해주기 때문에 각 칸이 0일 때만 다음에 방문할 수 있는 칸이 되기 때문이다. 

 

다 돌리고 box에 0(안 익은 토마토)가 남았다면 -1 리턴해주면 된다.

 

처음부터 다 익은 상황이었으면 answer 값이 1이 되므로 마지막에 출력하는 (answer - 1)이 0이 되어서, 모두 잘 익은 상황, 처음부터 모두 익은 상황을 커버할 수 있다.

 

3. 코드

더보기

 

/*
	토마토(3차원)
	BFS
	난이도 
*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <tuple>

using namespace std;

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int answer = 0;
	int M, N, H;
	cin >> M >> N >> H;

	vector<vector<vector<int>>> box(H, vector<vector<int>>(N, vector<int>(M, 0)));
	queue<tuple<int, int, int>> q;
	int dx[6] = {-1, 1, 0, 0, 0, 0};
	int dy[6] = {0, 0, -1, 1, 0, 0};
	int dz[6] = {0, 0, 0, 0, -1, 1};
	
	//입력
	for(int i=0;i<H;i++){
		for(int j=0;j<N;j++){
			for(int k=0;k<M;k++){
				cin >> box[i][j][k];
				if(box[i][j][k] == 1)
					q.push({i, j, k});
			}
		}
	}
	//BFS 시작
	while(!q.empty()){
		int z = get<0>(q.front());
		int x = get<1>(q.front());
		int y = get<2>(q.front());
		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 || nx>=N || ny<0 || ny>=M || nz<0 || nz>=H)
				continue;
			if(box[nz][nx][ny] != 0)
				continue;
			box[nz][nx][ny] = box[z][x][y] + 1;
			q.push({nz, nx, ny});
		}
	}

	//다 익을 수 없는 경우 체크, 토마토가 익는 데 걸리는 최대 시간 찾기
	for(int i=0;i<H;i++){
		for(int j=0;j<N;j++){
			for(int k=0;k<M;k++){	
				if(box[i][j][k] == 0){
					cout << "-1\n";
					return 0;
				}
				answer = max(answer, box[i][j][k]);
			}
		}
	}
	
	//1부터 셌으니까 -1 해서 출력
	cout << answer - 1 << "\n";

	return 0;
}

 

4. 느낀점

1) 잘 안 다뤄본 3차원 BFS를 하다 보니까 인덱스 설정이 헷갈려서 실수를 많이 했다.

2) 마지막에 안 익은 토마토가 있는지 확인하기 위한 루프를 돌아서 그런지 다른 풀이들보다 시간이 약간 더 걸린다.

   -> 변수가 많아지더라도 시간을 절약하는 것이 좋은지, 가시성과 명확성을 높이기 위해 각 프로세스를 구분하는 게 좋은지 고민해보야 할 것 같다.

3) 3차원 벡터 초기화와 함께 선언하는 게 많이 귀찮다. 더 편한 방법이 있는지 찾아보면 좋을 것 같다.

'알고리즘 > 백준' 카테고리의 다른 글

[백준/17070] 파이프 옮기기 1  (0) 2020.10.18
[백준/5557] 1학년  (1) 2020.10.18
[백준/1261] 알고스팟  (0) 2020.10.16
[백준/9655] 돌 게임  (0) 2020.10.16
[백준/2606] 바이러스  (0) 2020.10.10

1. 문제

문제 링크 : www.acmicpc.net/problem/2606

 

2606번: 바이러스

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어��

www.acmicpc.net

컴퓨터 간의 연결 정보가 주어지고 바이러스에 감염된 컴퓨터와 연결된 컴퓨터들이 감염된다.

1번 컴퓨터에 의해서 감염되는 컴퓨터의 개수를 구하는 문제.

 

2. 풀이

전형적인 DFS, BFS 문제(저는 DFS로 풀어봤습니다).

dfs 함수는 자기 자신을 포함해서 자기 자신으로부터 감염되는 컴퓨터들의 개수를 리턴합니다.

연결된 컴퓨터를 방문할 때 방문한 적이 있다면 그 컴퓨터는 이미 감염된 컴퓨터이므로 0을 리턴해줍니다.

ex) (2, 3), (2, 4), (2, 7) 연결쌍이 있고 어느 컴퓨터도 방문한 적이 없다면 다면 2, 3, 4, 7 총 4를 리턴

다만 1번 컴퓨터에 의해서 감염되는 컴퓨터의 개수를 구하는 것이므로 최종 결과값에서 1번 컴퓨터를 빼줘야 합니다.

 

 

3. 코드

더보기

 

/*
	바이러스
	DFS
	난이도
*/
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int N, M;
vector<vector<int>> links; // 컴퓨터 간 연결 정보
vector<bool> visited; // 방문 확인

int dfs(int cur){
	if(visited[cur])
		return 0;
	visited[cur] = true;
	int cnt = 1; // 자신이 감염되므로 1부터 시작한다.
	for(auto next : links[cur])
		cnt += dfs(next);
	return cnt;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin >> N >> M;

	links.reserve(N+1);
	visited.reserve(N+1);

	fill(visited.begin(), visited.end(), false);
	
	for(int i=0;i<M;i++){
		int a, b;
		cin >> a >> b;
		links[a].push_back(b);
		links[b].push_back(a);
	}

	cout << dfs(1) - 1 << endl; // 1번 노드 제외

	return 0;
}

 

4. 느낀점

1) 블로그 개설하고 처음 올리는 거라 포맷 등 포스팅에 부족함을 많이 느꼈다.

2) 코드의 길이와 가시성 사이에 고민하다보니 코드가 이도저도 아니게 되는 것 같다.(전역변수 사용 + reserve 사용, answer 미사용 등)

'알고리즘 > 백준' 카테고리의 다른 글

[백준/17070] 파이프 옮기기 1  (0) 2020.10.18
[백준/5557] 1학년  (1) 2020.10.18
[백준/1261] 알고스팟  (0) 2020.10.16
[백준/9655] 돌 게임  (0) 2020.10.16
[백준/7569] 토마토  (0) 2020.10.10

+ Recent posts