16236번: 아기 상어
N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가��
www.acmicpc.net
- 먼저, 상어의 현재 위치에서 도착 할 수 있는 공간과 없는 공간(자신보다 크기가 큰 물고기)을 구별하고, 지나갈 수 있는 공간이라면 해당 위치까지의 거리를 구해놓는다.
- BFS 를 이용해 모든 위치에 대해서 최단 거리를 구해놓고, 지나갈 수 없는 공간은 이상치를 저장해 놓는다.
- 공간의 최대 넓이는 20 x 20 이므로 완전 탐색을 통해 위에서 구한 정보들로부터 가장 가까운 위치를 구한다.
- 가장 가까운 위치에 있는 물고기를 먹는 처리를 해준다(상어 위치, 크기, 물고기 사라짐 처리 등)
- 이 때 (0,0) 에서 (n,n) 의 방향으로 탐색할 경우 자연스럽게 "거리가 가까운 물고기가 많다면 가장 위에 있는 물고기, 그러한 물고기가 여러마리라면 가장 왼쪽에 있는 물고기를 먹는다" 라는 조건이 충족된다.
- 만약 BFS 수행 후에 모든 공간에 대해서 이상치가 저장되어 있다면, 상어가 먹을 수 있는 물고기가 없기 때문에 종료해준다.
#include <iostream>
#include <algorithm>
#include <queue>
#define Point pair<int,int>
using namespace std;
int n;
int space[20][20]; // 실제 물고기들 정보
int visited[20][20]; // 각 위치까지의 거리에 대한 정보
Point shark_pos; // 상어의 현재 위치
int shark_size = 2; // 상어 현재 크기
int eatten = 0; // 상어가 현재 사이즈에서 먹은 물고기 수
int timer = 0;
int dir[4] = {1, -1, 0, 0};
void distance() // 물고기 현재 위치로부터 NxN 크기의 각 위치까지의 최단거리를 갱신하는 함수
{
for(int i = 0 ; i < n ; i ++)
{
for(int j = 0 ; j < n ; j++)
{
visited[i][j] = 0; // 거리 정보 초기화
if(space[i][j] > shark_size) // 지나갈 수 없는 칸에 대해서는 1000 으로 설정
visited[i][j] = 1000;
}
}
int dist = 0;
queue<Point> q; // 각 위치에 대해서 BFS
q.push(shark_pos); // 상어의 현재 위치부터 시작해서
visited[shark_pos.first][shark_pos.second] = 1000;
while(!q.empty()) // 상어가 도착할 수 있는 곳은 전부 탐색
{
int size = q.size();
for(int i = 0 ; i < size ; i++)
{
Point temp = q.front();
for(int j = 0, r, c ; j < 4 ; j++)
{
r = temp.first + dir[j];
c = temp.second + dir[3 - j];
if(0 <= r && r < n && 0 <= c && c < n)
{
if(visited[r][c] == 0)
{
q.push(Point(r,c));
visited[r][c] = dist + 1;
}
}
}
q.pop();
}
dist++;
}
for(int r = 0 ; r < n ; r++)
{
for(int c = 0 ; c < n ; c++)
{
if(visited[r][c] == 0) visited[r][c] = 1000; // 만약 0 인 칸이 있으면, 도달할 수 없는 곳이라는 뜻이기 때문에 1000 으로 설정
}
}
}
int check() // 물고기를 먹을지, 못 먹는지 체크해서 처리해주는 함수
{
int cur_time = 1000, x, y;
distance(); // 현재 물고기 위치에서 각 위치까지의 최단거리 업데이트
for(int r = 0 ; r < n ; r++)
{
for(int c = 0 ; c < n ; c++)
{
if(space[r][c] != 0 && space[r][c] < shark_size) // 먹을 수 있는 물고기 중에
{
if(visited[r][c] < cur_time) // 가장 최단거리에 있는 물고기를 선택
{ // 왼위에서 오른아래로 탐색하기 때문에, 같은 거리의 물고기에 대한 조건 충족
x = r;
y = c;
cur_time = visited[r][c];
}
}
}
}
if(cur_time == 1000) return 0; // 먹을 수 있는 물고기가 없을 경우 cur_time 이 업데이트 되지 않아서 1000 이 유지된다.
// 물고기를 먹을 수 있다면
timer += cur_time; // 해당 위치까지 가는 시간만큼 더해주고
shark_pos = Point(x,y); // 상어의 위치를 옮겨주고
space[x][y] = 0; // 해당 위치의 물고기를 없애주고
eatten++; // 먹은 횟수 1 증가시켜주는데
if(eatten == shark_size) // 만약 자신의 크기와 같은 수의 물고기를 먹은 상태라면
{
shark_size++; // 물고기 크기 증가시켜줌
eatten = 0;
}
return 1; // 다시 반복
}
int main(void)
{
cin.tie(0);
ios_base::sync_with_stdio(0);
cin >> n;
for(int r = 0 ; r < n ; r++)
{
for(int c = 0 ; c < n ; c++)
{
cin >> space[r][c];
if(space[r][c] == 9)
{
shark_pos = Point(r,c); // 상어의 위치를 업데이트 시켜주고
space[r][c] = 0; // 상어는 움직일 예정이므로 빈칸인 0 으로 표시
}
}
}
while(check()) {} // 더 이상 먹을 수 있는 물고기가 없을 때 까지 반복
cout << timer << '\n';
}
'PS > BOJ' 카테고리의 다른 글
[백준] 16566.cpp : 카드 게임 (0) | 2020.07.19 |
---|---|
[백준] 15650.cpp : N과 M (2) (0) | 2020.07.17 |
[백준] 15686.cpp : 치킨 배달 (0) | 2020.07.15 |
[백준] 14500.cpp : 테트로미노 (0) | 2020.07.13 |
[백준] 17298.cpp : 오큰수 (0) | 2020.07.12 |