Programming Practice/BOJ

[BOJ] 백준 16236 아기상어 (C++)

Cage 2022. 4. 19. 22:59

알고리즘 문제 풀이

문제

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

 

16236번: 아기 상어

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

www.acmicpc.net


풀이

BFS 방식의 탐색을 이용해야하는데 까다로운 조건이 있다.

1. 상어보다 작은 물고기만 먹을 수 있고, 같을 경우는 통행만 가능하고, 상어보다 큰 물고기가 있으면 통행이 불가능함.

2. 자신의 크기와 같은 숫자의 물고기를 먹어야 자신의 크기가 증가함.

3. 자신으로부터 위치가 같은 물고기가 있다면 윗쪽이 우선되며 그 다음은 왼쪽이 우선됨.

 

이라는 조건이 있어서 현재 자신의 위치로부터 통행가능한 곳의 거리를 계산하여 저장하고 먹을 수 있는 물고기의 좌표와 그곳까지의 거리를 따로 계산해서 저장해두어야한다. 동시에 이동했을 경우 다시 너비탐색을 통해 계산하여 다음 이동 목표지점을 정해야한다.


소스 코드

// 헤더파일
#define ll long long int
#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <map>
#include <cctype>
#include <set>
#include <string.h>

using namespace std;

int caa = 0;
int mmap[20][20];
int baby_size = 2;
int sizecnt = 0;
int mdistance = 0;
int visited[20][20];
int N, startx, starty;
vector <pair <pair<int, int>, int>> eat;

int dx[4] = { 1, 0, -1, 0 };
int dy[4] = { 0, 1, 0, -1 };

bool check(int y, int x) {
	if (y < 0 || y >= N || x < 0 || x >= N)
		return false;
	else
		return true;
}

// 시간을 재야해서 못 씀
/*
bool sorting(pair <int, int> p, pair <int, int> p2) {
	int v1, v2;
	v1 = p.first + p.second;
	v2 = p2.first + p.second;

	if (v1 == v2) {
		if (p.first == p2.first)
			return p.second < p2.second;
		else
			return p.first < p2.first;
	}

	return v1 < v2;
}
*/

void BFS(int y, int x) {
	eat.clear();
	memset(visited, 0, sizeof(visited));

	int eat_distance = 1e5;
	queue<pair<int, int>> q;

	//visited[y][x] = 1;
	q.push({ y, x });

	while (!q.empty()) {
		int px = q.front().second;
		int py = q.front().first;
		q.pop();

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

			if (visited[ny][nx] == 0 && check(ny, nx) && baby_size >= mmap[ny][nx]) {
				visited[ny][nx] = visited[py][px] + 1;

				if (baby_size > mmap[ny][nx] && mmap[ny][nx] > 0) {
					if (eat_distance >= visited[ny][nx]) {
						eat_distance = visited[ny][nx];
						eat.push_back({ { eat_distance, ny }, nx });
						//cout << "dis = " << eat_distance << '\n';
					}
				}

				q.push({ ny, nx });
			}
		}
	}
}

int main() { 
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> N;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> mmap[i][j];
			if (mmap[i][j] == 9) {
				mmap[i][j] = 0;
				startx = j;
				starty = i;
			}
		}
	}

	while (1) {
		BFS(starty, startx);
		//cout << "sy = " << starty << "| sx = " << startx << '\n';
		if (eat.empty())
			break;

		else {
			sort(eat.begin(), eat.end());

			sizecnt++;
			mdistance += eat[0].first.first;
			mmap[eat[0].first.second][eat[0].second] = 0;
			startx = eat[0].second;
			starty = eat[0].first.second;
			if (baby_size == sizecnt) {
				baby_size++;
				sizecnt = 0;
			}
		}
	}

	cout << mdistance << '\n';
}