본문 바로가기

모각코

3회차 결과

유사한 BFS문제를 2개 풀면서 익숙하게 만들었다. BOJ의 토마토와 연구소2를 풀었다. 유사한 문제를 풀면서 더욱 꼼꼼히 공부할 수 있었다.

 

 

 

 

(토마토)

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

public class Main {
  public static int[][] box;
  public static int[] dx = {0, 0, -1, 1};
  public static int[] dy = {-1, 1, 0, 0};
  public static int N, M;
  
  public static void main(String[] args) throws IOException{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String[] line = br.readLine().split(" ");
    N = Integer.parseInt(line[1]);
    M = Integer.parseInt(line[0]);
    box = new int[N][M];
    for(int i=0; i<N; i++){
      line = br.readLine().split(" ");
      for(int j=0; j<M; j++){
        box[i][j] = Integer.parseInt(line[j]);
      }
    }

    // 하루가 지나면 익는다!
    // 1:익은토마토
    // 0:익지않은
    // -1: empty!

    // 유의: 저쪽에서 익어오는 거, 이쪽에서 익어오는 거.. 동시에 고려해야 함
    int[][] visit = new int[N][M];
    Queue<int[]> q = new LinkedList<>();
    // 익은 토마토 공평하게 먼저 q에 넣어두기 (거기서부터 공평히 익어가야 하니까)
    for(int i=0; i<N; i++){
      for(int j=0; j<M; j++){
        if(box[i][j] == 1){
          q.add(new int[]{i, j});
        }
      }
    }
    // 위에서 익토를 q에 넣어줬으니, poll만 해서 진행하면 된다. (익토 최소 1개 존재)
    while(!q.isEmpty()){
      int[] now = q.poll();
      for(int k=0; k<4; k++){
        int x = now[1] + dx[k];
        int y = now[0] + dy[k];
        if(x<0||y<0||y>=N||x>=M)
          continue;
        if(box[y][x]==0 && visit[y][x]==0){
          visit[y][x] = visit[now[0]][now[1]] + 1;  // 하루하루..
          box[y][x] = 1; // 익었다..
          q.add(new int[]{y, x});
        }
      }
    }
    // visit에서 가장 큰 값이, 모두 익을 때 까지의 최소 날짜다.
    int res = 0;
    int tmp = 0;
    for(int i=0; i<N; i++){
      for(int j=0; j<M; j++){
        if((tmp = visit[i][j]) > res){
          res = tmp;
        }
      }
    }
    if(!isPossible(box)){
      res = -1;
    }
    System.out.println(res);
  }

  public static boolean isPossible(int[][] box){
    for(int i=0; i<N; i++){
      for(int j=0; j<M; j++){
        if(box[i][j] == 0){
          return false;
        }
      }
    }
    return true;
  }
}

 

(연구소2)

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

public class Main {
  public static int[][] map;
  public static int[] dx = {0, 0, -1, 1};
  public static int[] dy = {-1, 1, 0, 0};
  public static int N, M;
  
  public static void main(String[] args) throws IOException{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String[] line = br.readLine().split(" ");
    N = Integer.parseInt(line[0]); // 연구소 크기
    M = Integer.parseInt(line[1]); // 놓을 바이러스 개수
    
    // 0: 빈칸
    // 1: 벽
    // 2: 바이러스를 놓을 수 있는 곳

    // 맵 구성 & 바이러스 놓을 후보지 candi 준비!
    map = new int[N][N];
    List<int[]> candi = new ArrayList<>();
    for(int i=0; i<N; i++){
      line = br.readLine().split(" ");
      for(int j=0; j<N; j++){
        map[i][j] = Integer.parseInt(line[j]);
        if(map[i][j] == 2){
          candi.add(new int[]{i, j});
        }
      }
    }

    // 바이러스 놓을 M조합 구하기
    // - 헉 가변 M조합이라 반복문으로 구현이 난감하네
    // - 백트래킹을 사용하자!
    Map<Integer, Boolean> visited = new HashMap<>();
    for(int i=0; i<candi.size(); i++){
      visited.put(i, false);
    }
    List<int[]> output = new ArrayList<>();
    combination(candi, visited, 0, candi.size(), M, output);
    
    List<Integer> results = new ArrayList<>();
    // 조합대로 바이러스 놓고 BFS 해보자. 
    // 최소시간인 조합 경우가 result 상황이다.
    for(int i=0; i<output.size(); i+=M){
      // map_에 map 복사
      int[][] map_ = new int[N][N];
      for(int a=0; a<N; a++){
        for(int b=0; b<N; b++){
          map_[a][b] = map[a][b];
        }
      }
      
      List<int[]> virus3 = output.subList(i, i+M);
      for(int[] point : virus3){
        map_[point[0]][point[1]] = -1; // 바이러스는 -1이다. 
      }
      // 2와 0은 공간
      // 1은 벽
      int day = BFS(map_);

      // 결과값 계산하기 (퍼지는 최종 시간은? => 가장큰요소값임)
      results.add(day);
    }
    int min = Integer.MAX_VALUE;
    boolean flag = false;
    for(int num : results){
      if(num != -1){
        flag = true;
        if(num < min){
          min = num;
        }
      }
    }
    if(flag)
      System.out.println(min);
    else
      System.out.println(-1);
  }

  public static boolean emptySpace(int[][] map){
    for(int i=0; i<N; i++){
      for(int j=0; j<N; j++){
        if(map[i][j] == 0)
          return true;
      }
    }
    return false;
  }
  
  
  public static int BFS(int[][] map){
    Queue<int[]> q = new LinkedList<>();
    int[][] visited = new int[N][N];
    int[][] origin = new int[N][N];
    // 바이러스 인 거 먼저 q에 넣기
    for(int i=0; i<N; i++){
      for(int j=0; j<N; j++){
        origin[i][j] = map[i][j];
        if(map[i][j] == -1){
          q.add(new int[]{i, j});
        }
        visited[i][j] = 0;
      }
    }
    int day = 0;
    // 바이러스들 동시에 퍼지기 시작
    for(int i=0; i<N; i++){
      for(int j=0; j<N; j++){
        while(!q.isEmpty()){
          int[] point = q.poll();
          for(int k=0; k<4; k++){
            int x = point[1] + dx[k];
            int y = point[0] + dy[k];
            if(x<0||y<0||x>=N||y>=N)
              continue;
            if(map[y][x]==2||map[y][x]==0){
              if(visited[y][x] == 0){
                q.add(new int[]{y, x});
                day = visited[point[0]][point[1]] + 1;
                visited[y][x] = day; // 날짜(:=공간)
                map[y][x] = -1;
              }
            }
          }
        }          
      }
    }
    // visited에서 가장 큰 값이 최종소요일이다.
    // visitied에서 기존 벽을 세워보자.
    for(int i=0; i<N; i++){
      for(int j=0; j<N; j++){
        if(origin[i][j]==-1) // visited에 바이러스 있던 곳 반영
          visited[i][j] = -1;
        if(origin[i][j]==1) // visited에 벽 반영
          visited[i][j] = -9;
      }
    }
    int res = 0;
    for(int[] nums : visited){
      for(int num : nums){
        if(num == 0){
          return -1; // 바이러스 안퍼진 곳, 즉 0이 있으면 바로 -1 때리기 
        }
        if(num > res){
          res = num;
        }
      }
    }
    
    return res;
  }

  public static void combination(List<int[]> arr, Map<Integer, Boolean> visited, int start, int n, int r, List<int[]> output){
    if(r == 0){
      for(int i=0; i<n; i++){
        if(visited.get(i))
          output.add(arr.get(i));
      }
    }
    for(int i=start; i<n; i++){
      visited.put(i, true);
      combination(arr, visited, i+1, n, r-1, output);
      visited.put(i, false);
    }
  }
}

 

반응형

'모각코' 카테고리의 다른 글

5회차 결과  (0) 2023.08.06
4회차 결과  (0) 2023.07.30
2회차 결과  (0) 2023.07.11
1회차 결과  (0) 2023.07.07
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 2023년 모각코  (0) 2023.07.07
다른 블로그