티스토리 뷰

알고리즘/백준

백준 / BOJ / 16236 아기상어 C++

4567은 소수 2020. 11. 15. 03:33

www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

삼성 SW 기출문제로도 유명한 아기 상어 문제입니다. 상어 위치로부터 문제로부터 요구하는 물고기의 위치까지 최단 거리를 구하여 계속 더하면 되므로 bfs를 사용하였습니다. 

 

처음에는 상어의 현재 위치에서 $n^2$개 중 먹을 수 있는 물고기를 체크하고, 이 물고기들을 bfs를 이용하여 최단 거리와 어떤 물고기를 먹을 지 구한 뒤 while문으로 동일하게 반복하였습니다. 그러니 $O(n^6)$이 되어 시간초과가 떴습니다. (bfs : $O(n^2)$, while : $O(n^2)$)

 

시간을 줄이기 위해 $n^2$ 중 먹을 수 있는 물고기를 체크하는 과정 없이 bfs를 이용하여 먹어야하는 물고기의 좌표와 check배열을 이용하여 해당 좌표까지의 거리를 구하였습니다.

그리하여 $O(n^4)$ 으로 해결할 수 있습니다.

 

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

using namespace std;

int n;
int Map[21][21];
pair<pair<int, int>,int>shark;
int dy[4] = { 0,0,-1,1 };
int dx[4] = { 1,-1,0,0 };

int dist = 987654321;
int eat_x = 0;
int eat_y = 0;
int check[21][21];

void make_map()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> Map[i][j];
			if (Map[i][j] == 9) {
				shark.first = { i,j };
				shark.second = 2;
			}
			check[i][j] = -1;
		}
	}
}

void bfs(pair<pair<int,int>,int>S)
{
	int w = S.second;
	int Y = S.first.first;
	int X = S.first.second;
	check[Y][X] = 0;

	queue<pair<int, int>>q;
	q.push({ Y,X });

	while (!q.empty())
	{
		int y = q.front().first;
		int x = q.front().second;
		q.pop();

		for (int i = 0; i < 4; i++) {
			int ny = y + dy[i];
			int nx = x + dx[i];

			if (ny >= 1 && ny <= n && nx >= 1 && nx <= n)
			{
				if (check[ny][nx] != -1 || Map[ny][nx] > w) {
					continue;
				}

				check[ny][nx] = check[y][x] + 1;

				if (Map[ny][nx] > 0 && Map[ny][nx] < w) {
					if (dist > check[ny][nx]) {
						eat_y = ny;
						eat_x = nx;
						dist = check[ny][nx];
					}

					else {
						if (dist == check[ny][nx]) {
							if (eat_y == ny) {
								if (eat_x > nx) {
									eat_x = nx;
								}
							}
							else if (eat_y > ny) {
								eat_y = ny;
								eat_x = nx;
							}
						}
					}
				}
				q.push({ ny,nx });
			}
		}
	}
}

int solve()
{
	int time = 0;
	int cnt = 0;
	
	while (1)
	{
		memset(check, -1, sizeof(check));
		eat_x = 0;
		eat_y = 0;
		dist = 987654321;

		bfs(shark);

		if (eat_x == 0 && eat_y == 0)
			break;

		time += check[eat_y][eat_x];
		cnt++;
		Map[eat_y][eat_x] = 9;
		Map[shark.first.first][shark.first.second] = 0;
		shark.first = { eat_y,eat_x };

		if (cnt == shark.second) {
			cnt = 0;
			shark.second++;
		}
	}

	return time;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	make_map();
	int answer = solve();
	cout << answer;
}

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

백준 / BOJ / 1764 듣보잡 C++  (0) 2020.11.19
백준 / BOJ / 5557 1학년 C++  (0) 2020.11.16
백준 / BOJ / 15937 두 박스 C++  (0) 2020.11.12
백준 / BOJ / 2636 치즈 C++  (0) 2020.11.10
백준 / BOJ / 1946 신입 사원 C++  (0) 2020.11.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/12   »
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
글 보관함