반응형

문제 출처 :

 

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

 

 

 

 

알고리즘 분석 :


문제 해결에 필요한 사항

1. 순열

2. bfs

3. 문제 이해

 

이 문제는 주어진 비활성 바이러스(2) 중 m개를 뽑아 활성 바이러스(3)으로 바꿔주고, 그 후 bfs를 통해 활성 바이러스는 상/하/좌/우 로 움직이도록 만들어주면 된다.

 

이때 도로(0)을 지나갈 때는 활성 바이러스가 되고 비활성바이러스는 활성바이러스를 만나면 활성바이러스가 됨을 이용하면 된다. 

 

 

 

 

 

소스 코드 : 

 
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

#define ROAD 0
#define NON_ACTIVE_VIRUS 2
#define ACTIVE_VIRUS 3
#define INF 987654321
using namespace std;
typedef pair<int, int> pii;

int n, m;
int arr[52][52];
bool visit[12];
vector<pii> virus;

// for bfs
int map[52][52];
int road;

int dy[4] = { -1,0,1,0 };
int dx[4] = { 0,-1,0,1 };

queue<pair<pii, int> > q;

int ans = INF;
int bfs() {
	// clear queue
	while (!q.empty()) { q.pop(); }
	
	// virus qush
	for (int i = 0; i < 12; i++) {
		if (visit[i]) {
			q.push({ virus[i], 0 });

			// this position will be placed initial ACTIVE_VIRUS
			map[virus[i].first][virus[i].second] = ROAD;
			road++;
		}
	}

	int roadCnt = road;
	while (!q.empty()) {
		int y = q.front().first.first;
		int x = q.front().first.second;
		int cnt = q.front().second;
		q.pop();

		if (map[y][x] == ROAD) {
			map[y][x] = ACTIVE_VIRUS;
			roadCnt--;
		}
		else if (map[y][x] == NON_ACTIVE_VIRUS)
			map[y][x] = ACTIVE_VIRUS;
		else
			continue;

		if (roadCnt == 0)
			return cnt;

		for (int i = 0; i < 4; i++) {
			int ny = y + dy[i];
			int nx = x + dx[i];

			if (0 <= ny && ny < n && 0 <= nx && nx < n) {
				if (map[ny][nx] == ROAD) 
					q.push({ {ny,nx}, cnt + 1 });
				else if (map[ny][nx] == NON_ACTIVE_VIRUS) 
					q.push({ {ny,nx}, cnt + 1 });
			}
		}
	}

	return INF;
}

// copy map for check count of road and use in bfs
void copyMap(int map[][52]) {
	road = 0;

	// copy map
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			map[i][j] = arr[i][j];
			if (map[i][j] == ROAD) {
				road++;
			}
		}
	}
}

// basic combination
void combination(int pos, int cnt) {
	if (cnt == m) {
		copyMap(map);

		int ret = bfs();
		ans = min(ans, ret);
		return;
	}
	for (int i = pos; i < virus.size(); i++) {
		visit[i] = true;
		combination(i + 1, cnt + 1);
		visit[i] = false;
	}
}
int main() {
	scanf("%d %d", &n, &m);

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			scanf("%d", &arr[i][j]);
			if (arr[i][j] == NON_ACTIVE_VIRUS) {
				virus.push_back({ i,j });
			}
		}
	}
	combination(0, 0);

	printf("%d", ans == INF ? -1 : ans);

	return 0;
}

//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>

 

반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[17472번] 다리 만들기 2  (0) 2020.03.14
[SwExpertAcademy] 아나그램  (0) 2020.01.04
[SwExpertAcademy] Pole  (0) 2019.12.18
[SwExpertAcademy] 최대 부분 배열  (0) 2019.11.06
[Programmers] 섬 연결하기  (0) 2019.10.23