ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 17142 ( 연구소 3 )
    컴퓨터 공학 기초/알고리즘 (브루트포스) 2020. 7. 29. 16:56

    https://www.acmicpc.net/problem/17142

     

    17142번: 연구소 3

    인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고

    www.acmicpc.net

    해당 문제는 N과 K가 주어지며 N * N 개의 배열 안에서 바이러스를 퍼뜨려 맵 전체에 바이러스가 퍼질 수 있는 최단시간을 구하는 문제이다. 이때 조건은 바이러스는 무작위로 주어지며 해당 바이러스는 모두 활성화 되어있지 않으며 K개의 바이러스만 활성화 시켜 바이러스를 퍼트린다.

    따라서 K개의 바이러스 조합을 만들어 어떤 바이러스 조합이 최소의 시간으로 맵 전체에 바이러스를 퍼트릴 수 있는지 구하면 된다.

    풀이 :

    1. DFS를 사용하여 어떤 위치의 바이러스를 활성화 시킬지 조합으로 구성한다.

    2. 1에서 선택한 조합으로 Queue에 해당 조합의 바이러스를 Push 한 뒤 BFS를 사용하여 해당 조합의 바이러스가 전부 퍼졌을 때의 경우를 구한다.

    + 주의사항

    BFS 를 사용하여 바이러스가 퍼지는 경우중 만약 바이러스가 퍼진 위치가 비활성화된 바이러스라면 시간만 +1 해주며 따로 Cnt 는 하지않는다. 왜냐하면 해당 위치의 바이러스를 1초 뒤 활성화 시키는 것이지 빈칸에 바이러스가 퍼지는 것이 아니기 때문이다. 추가로 바이러스가 퍼지는 위치가 빈 칸이라면 Cnt를 now.time +1 로 증가시켜 빈 칸으로 바이러스가 퍼졌을 때의 시간을 Cnt에 추가한다. 

     

    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;
    struct Node{
    	int y, x;
    	int cnt, time;
    };
    int minn = 1000000;
    int checkY[4] = { 0, 0, 1, -1 };
    int checkX[4] = { 1, -1, 0, 0, };
    int map[50][50];
    int visit[50][50];
    int cpMap[50][50];
    int n, k, byLen;
    vector<Node> byList;
    vector<Node> result;
    
    bool checkList(){
    	for (int i = 0; i < n; ++i){
    		for (int j = 0; j < n; ++j){
    			if (map[i][j] == 0 && visit[i][j] == 0) return false;
    		}
    	}
    	return true;
    }
    
    int bfs(vector<Node> result){
    	int resCnt = 0;
    
    	memcpy(visit, cpMap, 4 * 50 * 50);
    	queue<Node> qu;
    	for (int i = 0; i < k; ++i){
    		visit[result[i].y][result[i].x] = 1;
    		qu.push(result[i]);
    	}
    
    	while (!qu.empty()){
    		Node now = qu.front();
    
    		for (int i = 0; i < 4; ++i){
    			int dy = now.y + checkY[i];
    			int dx = now.x + checkX[i];
    			if (dy < 0 || dx < 0 || dy >= n || dx >= n) continue;
    			if (map[dy][dx] == 1 || visit[dy][dx] == 1) continue;
                // 빈칸일 경우 현재 시간에 +1 값을 카운트한다.
    			if (map[dy][dx] == 0){
    				qu.push({ dy, dx, now.time + 1, now.time + 1 });
    			}
                // 비활성화 된 바이러스일 경우 시간만 변경한다.
    			if (map[dy][dx] == 2){
    				qu.push({ dy, dx, 0, now.time + 1 });
    			}
    			visit[dy][dx] = 1;
    		}
    		if (now.cnt > 0) resCnt = now.cnt;
    		qu.pop();
    	}
    	if (checkList() == true) return resCnt;
    	else return -1;
    }
    
    // 조합 선택
    void dfs(int level, int idx){
    	if (level == k){
    		int tmp = bfs(result);
    		if (tmp != -1){
    			if (minn > tmp) minn = tmp;
    		}
    		return;
    	}
    
    	for (int i = idx; i < byLen; ++i){
    		result.push_back(byList[i]);
    		dfs(level + 1, i + 1);
    		result.pop_back();
    	}
    }
    
    int main(){
    	//freopen_s(new FILE*, "tes.text", "r", stdin);
    	cin >> n >> k;
    	for (int i = 0; i < n; ++i){
    		for (int j = 0; j < n; ++j){
    			cin >> map[i][j];
    			if (map[i][j] == 2) byList.push_back({ i, j, 0, 0 });
    		}
    	}
    
    	byLen = byList.size();
    	dfs(0, 0);
    	if (minn == 1000000) minn = -1;
    	printf("%d", minn);
    }
    

    '컴퓨터 공학 기초 > 알고리즘 (브루트포스)' 카테고리의 다른 글

    백준 14226 (이모티콘)  (0) 2020.08.04
    백준 13913 (숨바꼭질 4)  (0) 2020.08.03
    백준 15686 (치킨 배달)  (0) 2020.07.21
    백준 15684 (사다리 조작)  (0) 2020.07.21
    백준 15683 (감시)  (0) 2020.07.20

    댓글

Designed by Tistory.