반응형

 

[광고 누르면 오늘의 행운 상승!!]

 

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

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다.  일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다.

www.acmicpc.net

BFS + 조합 문제

1. 리스트에 안전구역의 row , col 좌표를 담는다.

2. 조합으로 0~ 안전구역수까지의 숫자를 구한다.

3. 조합으로 구해진 3개의 구역을 VISIT 처리한다. (MAP을 변경하지 않는다) - 사실 큰 시간 차이는 없었다.

4. BFS를 시작한다. 이때 전염된 수만큼을 반환한다.

5. 안전구역수 - 전염구역 - 벽 3개 를 계산하여 경우의 수당 최대의 안전구역 수를 저장한다.

6. 끝

package Study0307;

import java.io.*;
import java.util.*;

class Pos{
	int row, col;
	public Pos(int row, int col) {
		this.row = row;
		this.col = col;
	}
}
public class 연구소 {
	public static final int[] dx = {1,0,-1,0};
	public static final int[] dy = {0,1,0,-1};
	public static int N,M,ans,safeZone,max = Integer.MIN_VALUE;;
	public static boolean[][] visit;
	public static boolean[] v;
	public static int[][] map;
	
	public static int arr[];
	public static int num[];
	
	public static ArrayList<Pos> list;
	public static ArrayList<Pos> virusList;
	public static Queue<Pos> q;
	
	public static void main(String[] args) throws Exception {
		System.setIn(new FileInputStream("test.txt"));
		Scanner sc = new Scanner(System.in);

		N = sc.nextInt();
		M = sc.nextInt();
		
		map	      = new int[N][M];
		list 	  = new ArrayList<>();
		virusList = new ArrayList<>();
		q         = new LinkedList<>();
		
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				map[i][j] = sc.nextInt();
				if(map[i][j] == 0) list.add(new Pos(i,j));
				if(map[i][j] == 2) virusList.add(new Pos(i,j));
			}
		}
		
		safeZone = list.size();
		arr = new int[3];
		num = new int[safeZone];
		v   = new boolean[safeZone];
		
		for (int i = 0; i < safeZone; i++) num[i] = i;
		
		permutation(0);
		System.out.println(max);
	}
	public static void permutation(int cnt) {
		if(cnt == 3) {
			//조합으로 만든 3가지 숫자
			visit = new boolean[N][M];
			
			for (int i = 0; i < 3; i++) {
				//map을 변경하지 않고 visit배열을 true로 바꾸어서 처리한다.
				visit[list.get(arr[i]).row][list.get(arr[i]).col] = true;
			}
			//안전구역 - 전염된 갯수 - 벽3개 = case N 의 결과값
			max = Math.max(max, safeZone - bfs() -3);
			return;
		}
		
		for (int i = 0; i < list.size(); i++) {
			if(!v[i]) {
				v[i] = true;
				arr[cnt] = num[i];
				permutation(cnt + 1);
				v[i] = false;
			}
		
		}
	}
	public static int bfs() {
		//바이러스를 q에 넣는다.
		for (Pos v : virusList) q.add(v);
		
		int cnt = 0;
		while(!q.isEmpty()) {
			Pos virus = q.poll();
			
			for (int i = 0; i < 4; i++) {
				int nx = virus.row + dx[i];
				int ny = virus.col + dy[i];
				
				if(nx < 0 || nx >= N || ny < 0 || ny >= M){
					continue;
				}
				if(map[nx][ny] == 1 || map[nx][ny] == 2 || visit[nx][ny]) {
					continue;
				}
				visit[nx][ny] = true;
				//전염 증가
				cnt++;
				
				q.add(new Pos(nx,ny));
			}
		}
		//전염된 만큼의 cnt 를 반환
		return cnt;
	}
}

 시간을 줄이기 위하여 여러가지 방법을 시도했으나 결국 다 비슷비슷한 시간이 나온다.

다른 사람의 코드를 보면 더 빠른데, 조합을 구하기 위하여 재귀 함수를 쓰지 않고 3중 FOR문으로 해결하였다.

함수 호출에 걸리는 시간의 차이인지 다른 차이인지 더 공부해야할 것 같다.

반응형

+ Recent posts