반응형
동요를 떠올리게 해주는 문제
문제의 키포인트는 아래와 같다.
1. BFS를 통해, 다음으로 먹을 물고기 위치 탐색
2. 이동 후 먹은 뒤 반복
처음에는, 그냥 BFS 없이 2중 포문으로 연산하고, 거리를 맨헤튼 거리로 계산했었는데 이는 잘못된 방법이었다.
왜냐하면, 아기상어는 자신보다 큰 물고기가 위치한 곳으로는 갈 수 없기 때문이다.
주석을 아주 세세하게 달아놨는데, 흐름은 이렇다
a. 아기상어 시작 위치 저장
b. 아기상어 시작 위치에서 bfs를 돌면서, 먹을 수 있는 물고기들을 찾을 때 마다 {그곳까지의 거리, 맵에서의 절대적인 위치} 를 저장한다.
그곳까지의 거리는 초수계산을 위해 사용되고, 맵에서의 절대적인 위치는 우선순위를 따지기 위해 사용된다.
c. 이를 토대로 cmp 비교함수로 정렬을 해준다
d. 정렬 후 맨 앞에 있는 것이 아기상어가 먹을 물고기이다. 이 값을 토대로 값을 업데이트해준다.
e. 아기상어는 자신의 몸집 크기의 물고기 갯수만큼 먹으면 몸집이 성장한다. 이를 적용해준다.
d. 반복
/*
distance를 맨헤튼거리로 표현하지 못하는 이유는, 아기상어는 자기보다 큰 물고기를 지나갈 수 없다.
bfs로 지정해줘야한다.
*/
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
int N;
int MAP[20][20];
int VISIT[20][20]; // VISIT과 depth 동시에 처리할 예정
int SX, SY, SS; // 아기상어 위치(SX, SY), 아기상어 크기(SS)
int TOTAL_TIME; // == TOTAL_DISTANCE와 같은 의미
int EAT_COUNT; // 먹은 물고기 수 체킹
int mx[4] = {-1, 1, 0, 0};
int my[4] = {0, 0, 1, -1};
vector<pair<int, int>> small_fishes; // {아기상어와의 거리 차이, 배열을 숫자로}
void bfs(int x, int y) {
queue<pair<int ,int>> que;
que.push({x, y});
VISIT[x][y] = 1; // 방문처리하기위해 1로. 문제에서는 시작지점까지 거리로 포함하지 않으니 맨 마지막에 -1해주면 거리계산됨.
while(!que.empty()) {
int xx = que.front().first;
int yy = que.front().second;
que.pop();
for(int i = 0; i < 4; i++) {
int tx = xx + mx[i];
int ty = yy + my[i];
if(tx < 0 || tx >= N || ty < 0 || ty >= N)
continue;
if(VISIT[tx][ty] == 0 && MAP[tx][ty] <= SS) { // 지나갈 수 있다면
VISIT[tx][ty] = VISIT[xx][yy] + 1;
que.push({tx, ty});
if(MAP[tx][ty] > 0 && MAP[tx][ty] < SS) { // 먹을 수 있는 물고기라면
int distance = VISIT[tx][ty] - 1; // 맨 첫 지점을 방문처리하기위해 1로 시작했기에 -1해줌.
int location = tx * N + ty;
small_fishes.push_back({distance, location});
}
}
}
}
}
int cmp(pair<int, int> a, pair<int, int> b) {
if(a.first == b.first)
return a.second < b.second;
else
return a.first < b.first;
}
int main() {
cin >> N;
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
cin >> MAP[i][j];
if(MAP[i][j] == 9) {
// 아기상어 위치와 크기 초기화
SX = i; SY = j; SS = 2;
MAP[i][j] = 0; // 9를 계속 남겨놓으면 이후 작업때 고려사항이 늘어날 수 있으니, 아기상어 위치저장 했으면 0으로 초기화
}
}
}
while(1) {
small_fishes.clear();
memset(VISIT, 0, sizeof(VISIT));
bfs(SX, SY);
sort(small_fishes.begin(), small_fishes.end(), cmp);
// 먹을 물고기 없으면 종료
if(small_fishes.size() == 0)
break;
// 물고기까지 닿는데의 시간 = 거리 더해줌
TOTAL_TIME += small_fishes.front().first;
// 아기상어 위치를 해당 위치로 재조정
int xx = small_fishes.front().second / N;
int yy = small_fishes.front().second % N;
SX = xx;
SY = yy;
// 먹은 물고기 자리는 0처리
MAP[xx][yy] = 0;
// 물고기 하나 먹음 처리
EAT_COUNT++;
// 먹은 물고기 수가 자신의 크기와 같아야 증가..
if(SS == EAT_COUNT) {
SS++;
EAT_COUNT = 0;
}
}
cout << TOTAL_TIME << "\n";
}
소요 시간 : 1시간
반응형
'[알고리즘 + 자료구조] > [백준]' 카테고리의 다른 글
[BaekJoon/백준] 1600번 말이 되고픈 원숭이 (0) | 2022.08.03 |
---|---|
[BaekJoon/백준] 1520번 내리막 길 (0) | 2022.08.02 |
[BaekJoon/백준] 2638번 치즈 (0) | 2022.07.31 |
[BaekJoon/백준] 15683번 감시 (0) | 2022.07.30 |
[BaekJoon/백준] 1062번 가르침 (0) | 2022.07.29 |