[C++][백준 14502] 연구소
- -
[문제]
14502번: 연구소
인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크
www.acmicpc.net
[문제 풀이]
n * m의 공간인 연구소에 바이러스가 퍼졌다. 2인 칸에서 부터 바이러스는 퍼지고 벽(1)의 부딪히거나 범위에 부딪히면 더 이상 퍼지지 못한다. 3개의 벽을 추가로 건설해서 바이러스를 최대한 덜 퍼트펴보자.
벽은 무조건 3개이고 0인 곳에 세울 수 있다.
그러니 0인 칸의 모든 좌표값을 알고 있을 때 이 중 3가지를 뽑아서 나올 수 있는 경우의 수가 문제에서 요구하는 거라고 봐도 무방할 것이다.
백준 n과 m 시리즈에서 자주 접했던 문제 즉, 0의 모든 좌표 (n) 에서 3개의 좌표(m)을 뽑아보자.
void backTrack(int cnt){
if(loc.size() == 3){
return;
}
for(int i = cnt;i<vec.size();i++){
if(visited[vec[i].first][vec[i].second] == 0){
visited[vec[i].first][vec[i].second] = 1;
loc.push_back(vec[i]);
backTrack(cnt + 1);
loc.pop_back();
visited[vec[i].first][vec[i].second] = 0;
}
}
return;
}
중복좌표를 만들지 않기 위하여 visited 처리와 loc이라는 벡터에 해당 위치를 넣고 빼고를 반복하면서 백트래킹을 해주었다.
이제 loc의 크기가 3 즉, 3개의 벽이 설치되었다면 bfs를 이용해서 2가 총 몇번을 갈 수 있는지 파악을 하자.
bool inRange(int x, int y){
if(x >= 0 && x < n && y >= 0 && y < m){
return true;
}
return false;
}
int bfs(){
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
viurs_visited[i][j] = 0;
}
}
//answer는 0의 숫자를 세는 변수. oneNum은 이미 세워져있는 벽의 숫자.
int answer = n * m - oneNum - 3;
for(int i = 0;i<loc.size();i++){
arr[loc[i].first][loc[i].second] = 1;
}
queue<pair<int,int> > q;
for(int i = 0;i<virus.size();i++){
q.push(virus[i]);
viurs_visited[virus[i].first][virus[i].second] = 1;
answer--;
}
while(q.size() > 0){
int curX = q.front().first;
int curY = q.front().second;
q.pop();
for(int i = 0;i<4;i++){
int nextX = curX + dx[i];
int nextY = curY + dy[i];
if(inRange(nextX,nextY) == true && viurs_visited[nextX][nextY] == 0){
//벽이 아니라면
if(arr[nextX][nextY] == 0){
viurs_visited[nextX][nextY] = 1;
q.push(make_pair(nextX,nextY));
answer--;
}
}
}
}
for(int i = 0;i<loc.size();i++){
arr[loc[i].first][loc[i].second] = 0;
}
return answer;
}
이와 같은 bfs를 통해서 우리들은 0의 좌표를 알 수가 있다.
bfs + 백트래킹 문제가 처음이면 어려울만 하지만 골드5를 넘어서는 bfs의 경우에는 조건이 추가되어 있거나 bfs + 이분탐색, 백트래킹 등으로 조건을 주는 경우가 많다. 처음에는 어려울 수 있지만 풀다보면 익숙해지니 양치기를 해보자.
[회고]
테스트 케이스가 좋아서 특별히 어려운 점은 없었다.
[코드]
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int answer;
int oneNum;
int arr[10][10];
int visited[10][10];
int viurs_visited[10][10];
int max_answer;
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
vector<pair<int,int> > vec;
vector<pair<int,int> > loc;
vector<pair<int,int> > virus;
bool inRange(int x, int y){
if(x >= 0 && x < n && y >= 0 && y < m){
return true;
}
return false;
}
int bfs(){
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
viurs_visited[i][j] = 0;
}
}
int answer = n * m - oneNum - 3;
for(int i = 0;i<loc.size();i++){
arr[loc[i].first][loc[i].second] = 1;
}
queue<pair<int,int> > q;
for(int i = 0;i<virus.size();i++){
q.push(virus[i]);
viurs_visited[virus[i].first][virus[i].second] = 1;
answer--;
}
while(q.size() > 0){
int curX = q.front().first;
int curY = q.front().second;
q.pop();
for(int i = 0;i<4;i++){
int nextX = curX + dx[i];
int nextY = curY + dy[i];
if(inRange(nextX,nextY) == true && viurs_visited[nextX][nextY] == 0){
//벽이 아니라면
if(arr[nextX][nextY] == 0){
viurs_visited[nextX][nextY] = 1;
q.push(make_pair(nextX,nextY));
answer--;
}
}
}
}
for(int i = 0;i<loc.size();i++){
arr[loc[i].first][loc[i].second] = 0;
}
return answer;
}
void backTrack(int cnt){
if(loc.size() == 3){
if(max_answer < bfs()){
max_answer = bfs();
}
return;
}
for(int i = cnt;i<vec.size();i++){
if(visited[vec[i].first][vec[i].second] == 0){
visited[vec[i].first][vec[i].second] = 1;
loc.push_back(vec[i]);
backTrack(cnt + 1);
loc.pop_back();
visited[vec[i].first][vec[i].second] = 0;
}
}
return;
}
int main(){
cin>>n>>m;
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
cin>>arr[i][j];
if(arr[i][j] == 0){
vec.push_back(make_pair(i,j));
}
else if(arr[i][j] == 2){
virus.push_back(make_pair(i,j));
}
else if(arr[i][j] == 1){
oneNum++;
}
}
}
backTrack(0);
cout<<max_answer<<endl;
return 0;
}
'코딩테스트 > 백준_골드' 카테고리의 다른 글
[C++][백준 14503] 로봇 청소기 (1) | 2023.09.07 |
---|---|
[C++][백준 9205] 맥주 마시면서 걸어가기 (0) | 2023.09.06 |
[C++][백준 2573] 빙산 (0) | 2023.09.06 |
[C++] 미세먼지 안녕! (0) | 2023.09.05 |
[C++][백준 1062] 가르침 (1) | 2023.04.15 |
소중한 공감 감사합니다