#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class Fish {
public:
int row; //물고기 있는 행
int col; //물고기 있는 열
int size; //물고기 사이즈
//canEatFishVec에 있는것만 값 있음
int fishVecindex; //fishVec에서는 index가 몇번인지
int distance; //아기상어와의 거리
Fish(int r, int c, int s) {
row = r;
col = c;
size = s;
}
};
int n;
vector<vector<int>> board;
vector<Fish> fishVec; //전체 물고기
vector<Fish> canEatFishVec; //먹을 수 있는 물고기
int sharkRow, sharkCol, sharkSize, sharkEatNum; //아기상어 행, 열, 크기, 현재 먹은 물고기 갯수
int time = 0; //시간. 답
//동서남북
int dRow[4] = { 0,0,1,-1 };
int dCol[4] = { 1,-1,0,0 };
void bfs() {
//아기상어로부터의 거리 구하기
vector<vector<int>> distance(n, vector<int>(n, -1));
queue<pair<int, int>> q;
q.push({ sharkRow, sharkCol });
distance[sharkRow][sharkCol] = 0;
while (!q.empty()) {
int hereRow = q.front().first;
int hereCol = q.front().second;
int hereD = distance[hereRow][hereCol];
q.pop();
for (int i = 0; i < 4; i++) {
int thereRow = hereRow + dRow[i];
int thereCol = hereCol + dCol[i];
//범위안이고 내가 지나갈 수 있고 간 적 없다면
if (0 <= thereRow && thereRow < n &&
0 <= thereCol && thereCol < n &&
board[thereRow][thereCol] <= sharkSize &&
distance[thereRow][thereCol] == -1) {
distance[thereRow][thereCol] = hereD + 1;
q.push({ thereRow, thereCol });
}
}
}
//먹을 수 있는 물고기 체크
//먹을 수 있다 <=> 크기가 상어 크기 이하 && 막혀있지 않음 (distance != -1)
for (int i = 0; i < fishVec.size(); i++) {
if (fishVec[i].size < sharkSize && distance[fishVec[i].row][fishVec[i].col] != -1) {
//크기가 아기상어보다 작고 먹으러갈 수 있다면
canEatFishVec.push_back(fishVec[i]);
canEatFishVec.back().fishVecindex = i; //방금 넣은 애의 index
canEatFishVec.back().distance = distance[fishVec[i].row][fishVec[i].col]; //방금 넣은 애의 dist
}
}
}
//canEatFishVec의 몇번째 index를 먹으러 갈건지
void eat(int canEatFishVecIndex) {
board[sharkRow][sharkCol] = 0; //상어가 이동했으니까 원래 상어 자리는 빈 자리로
sharkRow = canEatFishVec[canEatFishVecIndex].row; //상어는 물고기 자리로 이동
sharkCol = canEatFishVec[canEatFishVecIndex].col;
time += canEatFishVec[canEatFishVecIndex].distance; //한칸 이동에 1초 걸리므로
board[sharkRow][sharkCol] = 9; //물고기 먹었으니까 그 자리에는 상어가
sharkEatNum++; //물고기를 먹는다
if (sharkSize == sharkEatNum) { //현재 상어 크기만큼 물고기 먹었으면
sharkSize++; //상어 크기 + 1
sharkEatNum = 0;
}
//먹은 물고기 fishVec에서 제거
//canEatFishVec은 while마다 새로 구하기 때문에 여기선 없애줄 필요 없음
int fishVecindex = canEatFishVec[canEatFishVecIndex].fishVecindex;
fishVec.erase(fishVec.begin() + fishVecindex);
}
int close() {
//다음에 먹을 물고기의 canEatFishVec에서의 index return
priority_queue<pair<pair<int, int>, pair<int, int>>> pq; //-거리, -row, -col, canEatFishVec에서의 index
for (int i = 0; i < canEatFishVec.size(); i++) {
pq.push({ {-1 * canEatFishVec[i].distance, -1 * canEatFishVec[i].row}, { -1 * canEatFishVec[i].col, i} });
}
int ret = pq.top().second.second; //index
return ret;
}
int main() {
scanf("%d", &n);
board = vector<vector<int>>(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &board[i][j]);
if (1 <= board[i][j] && board[i][j] <= 6) {
Fish f(i, j, board[i][j]);
fishVec.push_back(f);
}
else if (board[i][j] == 9) {
sharkRow = i;
sharkCol = j;
sharkSize = 2;
sharkEatNum = 0;
}
}
}
////////////////////////////
while (true) {
canEatFishVec.clear(); //매번 먹을 수 있는 물고기 새로 구하기
bfs(); //먹을 수 있는 물고기 목록 구하기. row, col, distance, fistVecIndex
if (canEatFishVec.empty()) {
break; //먹을 수 있는 물고기가 없다면
}
if (canEatFishVec.size() == 1) {
eat(0); //먹을 수 있는 물고기가 한마리라면 그 한마리 먹기. 하나니까 인덱스 무조건 0
}
else {
int eatIndex = close(); //가장 가까운 물고기가 canEatFishVec에서 몇번 index인지
eat(eatIndex); //그 물고기 먹으러 간다
}
}
cout << time;
return 0;
}
거리 -> bfs
https://www.acmicpc.net/problem/16236
16236번: 아기 상어
N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가��
www.acmicpc.net
'Baekjoon' 카테고리의 다른 글
[#15684] 사다리 조작 (0) | 2020.10.15 |
---|---|
[#14503] 로봇 청소기 (0) | 2020.10.13 |
[#14502] 연구소 (0) | 2020.10.12 |
[#14499] 주사위 굴리기 (0) | 2020.10.11 |
[#13458] 시험 감독 (0) | 2020.10.11 |