문제:
- 제목: 아기상어
- 링크 : https://www.acmicpc.net/problem/16236
해결 방식:
BFS (+로직)
- 얻어간점
- BFS의 도구화
- 구조체(+STL)의 자유로운 사용
- sort의 pair 로직
- 반례생성법
CODE
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;
int N;
int graph[21][21] = { 0, };
struct information {
int visited = 0;
int enabled = 0;
};
struct shark_info {
int shark_size = 2;
pair<int, int> shark_loc;
int count_of_eating_feed = 0;
int total_time = 0;
};
information visited[21][21]; //visited, enabled
int dr[4] = { -1,1,0,0 };
int dc[4] = { 0,0,-1,1 };
int init_time = 0;
void init_visited() {
memset(visited, 0, sizeof(visited));
}
int enable_check_according_to_shark_size(int shark_size) {
int candi_feed_cnt = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (graph[i][j] < shark_size && graph[i][j] > 0)
candi_feed_cnt++;
if (graph[i][j] <= shark_size || graph[i][j] == 9) {
visited[i][j].enabled = 1;
}
else {
visited[i][j].enabled = 0;
}
}
}
if (candi_feed_cnt == 0) return 0;
return candi_feed_cnt;
}
pair<int,int> next_feed(pair<int,int> cur_shark_loc, int shark_size) {
vector<pair<int,pair<int,int>>> candi_feeds_loc; //dist, r,c
int check = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (graph[i][j] < shark_size && graph[i][j]>0) {
int distance = visited[i][j].visited;
if (distance== 0) {
distance = 999;
}
candi_feeds_loc.push_back({ distance,{i,j} });
}
}
}
//std::pair는 기본적으로 첫 번째 요소(dist) → 두 번째 요소(r) → 세 번째 요소(c) 순서대로 자동 정렬됩니다.
sort(candi_feeds_loc.begin(), candi_feeds_loc.end());
return candi_feeds_loc[0].second;
}
shark_info meal_time(shark_info init_shark) {
init_visited();
if (enable_check_according_to_shark_size(init_shark.shark_size) == 0) {
cout << init_shark.total_time;
exit(0);
}
visited[init_shark.shark_loc.first][init_shark.shark_loc.second].visited = 0;
queue<pair<int,int>> q;
q.push(init_shark.shark_loc);
while (!q.empty()) {
pair<int,int> cur_loc = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
pair<int, int> next_loc = { cur_loc.first + dr[i], cur_loc.second + dc[i] };
if (next_loc.first >= N || next_loc.first < 0 || next_loc.second >= N || next_loc.second < 0)
continue;
if (visited[next_loc.first][next_loc.second].visited != 0)
continue;
if (visited[next_loc.first][next_loc.second].enabled != 1)
continue;
visited[next_loc.first][next_loc.second].visited = visited[cur_loc.first][cur_loc.second].visited + 1;
q.push(next_loc);
}
}
pair<int, int> cur_target_feed = next_feed(init_shark.shark_loc, init_shark.shark_size);
//can you go to the next feed?
int left_feed = enable_check_according_to_shark_size(init_shark.shark_size);
if (left_feed == 0) {
cout << init_shark.total_time;
exit(0);
}
else { //Let's eat the left food with first priroity
information next_shark_info = visited[cur_target_feed.first][cur_target_feed.second];
if (next_shark_info.visited == 0) { //shark can't move to the next direction "block"
cout << init_shark.total_time;
exit(0);
}
graph[cur_target_feed.first][cur_target_feed.second] = 0;
init_shark.count_of_eating_feed++;
if (init_shark.count_of_eating_feed == init_shark.shark_size) {
init_shark.shark_size++;
init_shark.count_of_eating_feed = 0;
}
init_shark.shark_loc = { cur_target_feed.first, cur_target_feed.second };
init_shark.total_time = init_shark.total_time + next_shark_info.visited;
return init_shark;
}
}
int main() {
cin.tie(0);
cout.tie(0);
iostream::sync_with_stdio(0);
//freopen("텍스트.txt", "r", stdin);
cin >> N;
shark_info init_shark;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> graph[i][j];
if (graph[i][j] == 9) {
init_shark.shark_loc.first = i;
init_shark.shark_loc.second = j;
graph[i][j] = 0;
}
}
}
while (1) {
shark_info next_shark = meal_time(init_shark);
init_shark = next_shark;
}
exit(0);
}