반응형
리뷰
어렵다고 생각이 들진 않았는데 생각보다 엣지케이스가 많아서 오답이 많이 노출되었다... 후
https://www.acmicpc.net/problem/17142
문제 풀이
- n과 m을 입력 받고 맵 정보를 초기화 한다. 만약 맵에 2가 존재한다면 Pos구조체 타입의 virus 벡터에 추가해 준다.
- 입력을 다 받고 나서 length 변수에 virus의 크기를 저장해 주고 dfs를 실행해 준다.
- dfs를 통해 virus의 크기만큼의 반복을 돌며 중복이 없고 순서가 있는 탐색을 진행해 준다.
- 기저조건은 level이 m이 도달했을 때이다, path 변수에 저장된 인덱스를 갖고 bfs를 실행해 준다.
- 방문 배열부터 초기화 해준다, 이때 벽의 경우에는 미리 0으로 초기화 해주고 나머지는 -1로 초기화 해준다.
- path에 저장된 인덱스를 갖는 virus 정보를 큐에 모두 추가해 주고, 현재 위치를 0으로 방문 처리해준다.
- 현재 위치로부터 4방향 탐색을 진행하며, 방문하지 않았고, 벽이 아닌 모든 부분을 탐색해 준다.
- 이때 활성화 되지 않은 바이러스를 방문할땐 거리를 0으로 체크해 주어야 한다.
- 만약 현재 좌표의 방문값이 ans보다 크거나 같을 경우 더 이상 탐색해 줄 필요가 없다. 매우 큰 값 리턴
- while이 종료되었다면 방문 배열에 -1 값이 존재하는지 체크해 준다. 있다면 역시 매우 큰 값을 리턴해 준다.
- 벽이 아닌 모든 부분을 탐색했다면 가장 큰 값을 max_val 변수에 저장해둔 뒤 해당 값을 리턴해 주면 된다.
- 매 탐색에서 bfs의 출력값을 ans의 최소값으로 갱신해 주고, 모든 탐색이 종료된 뒤 ans값을 출력해 주면 된다.
참고 사항
중복이 없고 순서가 있는 탐색을 할 경우엔 방문처리 및 이전값이 앞으로 올 값보다 커야 한다는 조건을 추가하면 된다.
예제 테스트케이스를 보니 선택한 바이러스가 아니라 해도 빈 칸으로 보지 않는다. 아래에 엣지케이스 몇개를 전달해 준다.
5 3
2 2 2 0 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
answer : 2
4 2
0 1 1 0
2 1 1 2
2 1 1 2
0 1 1 0
answer : 2
5 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
2 0 0 2 0
1 1 1 1 1
answer : 2
5 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 2 0 2 0
1 1 1 1 1
answer : 3
5 1
2 2 2 1 1
2 1 1 1 1
2 1 1 1 1
2 1 1 1 1
2 2 2 2 0
answer : 1
4 1
2 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
answer : 0
정답 코드
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int n, m, length, ans = 1e9;
int lst[50][50];
int visit[50][50];
int v[10] = { 0, };
int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };
struct Pos {
int x, y, d;
};
vector<Pos> virus;
void init() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (lst[i][j] == 1) visit[i][j] = 0;
else visit[i][j] = -1;
}
}
}
int bfs(vector<int>& path) {
queue<Pos> q;
init();
for (int i = 0; i < m; i++) {
Pos pos = virus[path[i]];
q.push(pos);
visit[pos.x][pos.y] = 0;
}
while (!q.empty()) {
Pos pos = q.front(); q.pop();
int cx = pos.x, cy = pos.y, cd = pos.d;
if (visit[cx][cy] >= ans) return 1e9;
for (int i = 0; i < 4; i++) {
int nx = cx + dx[i], ny = cy + dy[i], nd = cd + 1;
if (0 <= nx && nx < n && 0 <= ny && ny < n && visit[nx][ny] == -1 && lst[nx][ny] != -1) {
if (lst[nx][ny] == 2) visit[nx][ny] = 0;
else visit[nx][ny] = nd;
q.push({ nx, ny, nd });
}
}
}
int max_val = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (visit[i][j] == -1 && !lst[i][j]) return 1e9;
else max_val = max(max_val, visit[i][j]);
}
}
return max_val;
}
void dfs(int level, vector<int>& path) {
if (level == m) {
ans = min(ans, bfs(path));
return;
}
for (int i = 0; i < length; i++) {
if (v[i]) continue;
if (!path.empty() && i < path[level - 1]) continue;
v[i] = 1;
path.push_back(i);
dfs(level + 1, path);
path.pop_back();
v[i] = 0;
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> lst[i][j];
if (lst[i][j] == 2) virus.push_back({i, j, 0});
}
}
length = virus.size();
vector<int> path;
dfs(0, path);
if (ans == 1e9) cout << -1;
else cout << ans;
}
728x90
반응형
'알고리즘 공부 > C++' 카테고리의 다른 글
백준 2573번 빙산 C++ BFS, 완전 탐색, 시뮬레이션, 구현 (0) | 2024.09.06 |
---|---|
백준 15683번 감시 C++ 백트래킹, 구현, 시뮬레이션 (0) | 2024.09.04 |
백준 17406번 배열 돌리기4 C++ 백트래킹, 구현, 시뮬레이션 (0) | 2024.09.03 |
백준 17281번 ⚾ C++ 백트래킹, 구현, 시뮬레이션 (0) | 2024.09.03 |
백준 17484번 진우의 달 여행 (Small) C++ BFS, 너비 우선 탐색 (6) | 2024.09.02 |