알고리즘/백준 문제 풀이
[BOJ] 17141. 연구소 2
바켱서
2020. 10. 18. 20:51
https://www.acmicpc.net/problem/17141
접근 방법
전형적인 부르트 포스 방식으로
바이러스가 있을 수도 있는 장소를 기억을 해놓는 배열을 생성한다.
static ArrayList<Point> canVirus = new ArrayList<>();
map[i][k] = Integer.parseInt(st.nextToken());
if(map[i][k] == 2){
canVirus.add(new Point(i,k));
map[i][k] = 0;
}
그런 후 이 바이러스가 들어 있는 곳에서 문제에서 제시한 M개를 뽑으면 된다.
( 즉 , 바이러스Cm ← 조합의 의미 ) =⇒ 바이러스가 있을 수 있는 곳 중 M개를 순서 상관 없이 뽑기.
static void permutation(int n, int r, int peek, boolean[] virus){
if(r == 0){
setVirus = new ArrayList<>();
for(int i=0; i<canVirus.size(); i++) {
if(virus[i]){
setVirus.add(new Point(canVirus.get(i).x, canVirus.get(i).y));
map[canVirus.get(i).x][canVirus.get(i).y] = 2;
}
}
spreadVirus();
ans = Math.min(getTime(),ans);
for(int i=0; i<canVirus.size(); i++) {
map[canVirus.get(i).x][canVirus.get(i).y] = 0;
}
return;
}
for(int i=peek; i<n; i++){
virus[i] = true;
permutation(canVirus.size(), r-1, i+1, virus);
virus[i] = false;
}
}
이제 바이러스가 있는 곳의 위치를 setVirus에 담아주고
바이러스가 퍼지는 것을 보여주면 된다.
static void spreadVirus(){
visit = new int[N][N];
Queue<Point> queue = new LinkedList<>();
for(Point point : setVirus){
queue.add(point);
visit[point.x][point.y] = 1;
}
while(!queue.isEmpty()){
Point point = queue.poll();
for(int i=0; i<4; i++){
int nx = dx[i] + point.x;
int ny = dy[i] + point.y;
if(nx<0 || ny<0 || nx>=N || ny>=N) continue;
if(map[nx][ny] != 1 && visit[nx][ny] == 0){
visit[nx][ny] = visit[point.x][point.y] + 1;
map[nx][ny] = 2;
queue.add(new Point(nx,ny));
}
}
}
}
Need Know
- 브루트 포스
- 조합
전체 코드 ( Java )
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static int N;
static int M;
static int[][] map;
static int[] dx = {-1,1,0,0};
static int[] dy = {0,0,-1,1};
static ArrayList<Point> canVirus = new ArrayList<>();
static ArrayList<Point> setVirus;
static int[][] visit;
static int ans = Integer.MAX_VALUE;
public static void main(String[] args) throws IOException {
set();
solve();
bw.flush();
bw.close();
br.close();
}
static void set() throws IOException {
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][N];
for(int i=0; i<N; i++){
st = new StringTokenizer(br.readLine());
for(int k=0; k<N; k++){
map[i][k] = Integer.parseInt(st.nextToken());
if(map[i][k] == 2){
canVirus.add(new Point(i,k));
map[i][k] = 0;
}
}
}
}
static void solve() throws IOException {
permutation(canVirus.size(), M, 0, new boolean[canVirus.size()]);
if(ans == Integer.MAX_VALUE) bw.write(-1+"");
else bw.write((ans-1) +"");
}
static void permutation(int n, int r, int peek, boolean[] virus){
if(r == 0){
setVirus = new ArrayList<>();
for(int i=0; i<canVirus.size(); i++) {
if(virus[i]){
setVirus.add(new Point(canVirus.get(i).x, canVirus.get(i).y));
map[canVirus.get(i).x][canVirus.get(i).y] = 2;
}
}
spreadVirus();
ans = Math.min(getTime(),ans);
for(int i=0; i<canVirus.size(); i++) {
map[canVirus.get(i).x][canVirus.get(i).y] = 0;
}
return;
}
for(int i=peek; i<n; i++){
virus[i] = true;
permutation(canVirus.size(), r-1, i+1, virus);
virus[i] = false;
}
}
static void spreadVirus(){
visit = new int[N][N];
Queue<Point> queue = new LinkedList<>();
for(Point point : setVirus){
queue.add(point);
visit[point.x][point.y] = 1;
}
while(!queue.isEmpty()){
Point point = queue.poll();
for(int i=0; i<4; i++){
int nx = dx[i] + point.x;
int ny = dy[i] + point.y;
if(nx<0 || ny<0 || nx>=N || ny>=N) continue;
if(map[nx][ny] != 1 && visit[nx][ny] == 0){
visit[nx][ny] = visit[point.x][point.y] + 1;
map[nx][ny] = 2;
queue.add(new Point(nx,ny));
}
}
}
}
static int getTime(){
int ans = 0;
for(int i=0; i<N; i++){
for(int k=0; k<N; k++){
if(map[i][k] == 0) {
return Integer.MAX_VALUE;
}
ans = Math.max(ans, visit[i][k]);
}
}
return ans;
}
}
class Point {
int x,y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}