반응형
    
    
    
  https://www.acmicpc.net/problem/16234
16234번: 인구 이동
N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모
www.acmicpc.net


풀이
인접해있는 땅과의 인구수 차이가 L과 R 사이이면 국경선이 열리고 연합 내의 동일한 인구수를 가진다.
위 문제는 bfs, dfs 아무거나 사용해도 무관하기 때문에 본인이 원하는 걸 사용하면 된다.
필자는 bfs를 이용해서 문제를 풀었다.
while (true) {     visited = new boolean[N][N]; // 방문 유부     isMove = false; // 변경 유무 			     for (int i=0; i<N; i++) {         for (int j=0; j<N; j++) {             if (!visited[i][j]) bfs(i, j);         }     } 			     if (!isMove) break;     ans++; } 
해당 문제는 더 이상 인접한 땅과의 인구수 차이가 L과 R 사이가 없을 때까지 돌려야 한다.
그렇기 때문에 무한 반복문 안에 인구수 변경 유무를 판단할 isMove 변수를 넣은 후에 더 이상 위 조건이 없을 때까지 bfs를 돌린다.
public static void bfs(int x, int y) {     Queue<Position> q = new LinkedList<>();     ArrayList<Position> arrList = new ArrayList<>(); // 인구수를 평균내기 위한 배열 		     arrList.add(new Position(x, y)); // 시작 땅 추가     q.add(new Position(x, y));     visited[x][y] = true;     int sum = map[x][y]; 		     while(!q.isEmpty()) {         Position now = q.poll(); 			         for (int i=0; i<4; i++) {             int nx = now.x + dx[i];             int ny = now.y + dy[i]; 				             if (nx < 0 || nx > N-1 || ny < 0 || ny > N-1 || visited[nx][ny]) continue; 				             int sumxy = Math.abs(map[nx][ny] - map[now.x][now.y]); 				             // 조건에 해당하는 땅 (인구수 차이가 L과 R사이)             if (L <= sumxy && sumxy <= R) {                 sum += map[nx][ny]; 					                 arrList.add(new Position(nx, ny));                 q.add(new Position(nx, ny));                 visited[nx][ny] = true;             }         }     } 		     // 변경할 값이 존재할 경우     if (arrList.size() > 1) {         int num = sum / arrList.size();         for (int i=0; i<arrList.size(); i++) {             map[arrList.get(i).x][arrList.get(i).y] = num;         } 			         isMove = true;     } } 
bfs는 아주 기본적인 구조에서 인구수를 변경해야 하는 조건에 들어맞는 땅을 넣을 arrList 배열을 추가했다.
조건에 해당하는 땅을 arrList 배열에 입력한 후에 마지막에 arrList 배열의 크기가 2개 이상일 때 평균을 내서 땅의 인구수를 평균으로 변경한다.
변경해준 후에는 isMove 변수를 true로 바꾸면 된다.
<최종코드>
import java.io.*; import java.util.*;   public class Main {     static int[] dx = {-1, 0, 1, 0};     static int[] dy = {0, -1, 0, 1};     static int[][] map;     static boolean[][] visited;     static int N, L, R, ans;     static boolean isMove; 	     public static class Position {         int x;         int y; 		         public Position(int x, int y) {             this.x = x;             this.y = y;         }     } 	     public static void main(String[] args) throws IOException {         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));         StringTokenizer st = new StringTokenizer(br.readLine()); 		         N = Integer.parseInt(st.nextToken());         L = Integer.parseInt(st.nextToken());         R = Integer.parseInt(st.nextToken()); 		         map = new int[N][N];         for (int i=0; i<N; i++) {             st = new StringTokenizer(br.readLine());             for (int j=0; j<N; j++) {                 map[i][j] = Integer.parseInt(st.nextToken());             }         } 		         // 변경한 값이 없을 때까지 반복         while (true) {             visited = new boolean[N][N]; // 방문 유부             isMove = false; // 변경 유무 			             for (int i=0; i<N; i++) {                 for (int j=0; j<N; j++) {                     if (!visited[i][j]) bfs(i, j);                 }             } 			             if (!isMove) break;             ans++;         } 		         System.out.println(ans);     } 	     public static void bfs(int x, int y) {         Queue<Position> q = new LinkedList<>();         ArrayList<Position> arrList = new ArrayList<>(); // 인구수를 평균내기 위한 배열 		         arrList.add(new Position(x, y)); // 시작 땅 추가         q.add(new Position(x, y));         visited[x][y] = true;         int sum = map[x][y]; 		         while(!q.isEmpty()) {             Position now = q.poll(); 			             for (int i=0; i<4; i++) {                 int nx = now.x + dx[i];                 int ny = now.y + dy[i]; 				                 if (nx < 0 || nx > N-1 || ny < 0 || ny > N-1 || visited[nx][ny]) continue; 				                 int sumxy = Math.abs(map[nx][ny] - map[now.x][now.y]); 				                 // 조건에 해당하는 땅 (인구수 차이가 L과 R사이)                 if (L <= sumxy && sumxy <= R) {                     sum += map[nx][ny]; 					                     arrList.add(new Position(nx, ny));                     q.add(new Position(nx, ny));                     visited[nx][ny] = true;                 }             }         } 		         // 변경할 값이 존재할 경우         if (arrList.size() > 1) {             int num = sum / arrList.size();             for (int i=0; i<arrList.size(); i++) {                 map[arrList.get(i).x][arrList.get(i).y] = num;             } 			             isMove = true;         }     } } 
반응형
    
    
    
  '알고리즘 > DFS & BFS' 카테고리의 다른 글
| [백준]JAVA - 2206번: 벽 부수고 이동하기 (0) | 2022.11.08 | 
|---|---|
| [백준]JAVA - 1937번: 욕심쟁이 판다 (0) | 2022.11.07 | 
| [백준]JAVA - 14502번: 연구소 (0) | 2022.10.25 | 
| [백준]JAVA - 16236번: 아기 상어 (0) | 2022.10.20 | 
| [백준]JAVA - 1260번: DFS와 BFS (0) | 2022.10.19 |