본문 바로가기
Algorithm/Problem

인구 이동(BJ_G4_16234)

by 당진개발자 2024. 4. 22.

1. 문제 링크

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

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모

www.acmicpc.net


 

2. 나의 코드

메모리: 296944kb
시간: 676ms
코드 길이: 2333B
시간 복잡도 : O(N^4)
설명
- 0, 0부터 BFS 호출
- 마을이 형성되면 인구 이동 실시
- 방문하지 않은 모든 지점을 체크하면서 다른 마을이 있으면 위와 같은 로직 실행
- 인구 이동이 없으면 종료
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	static int[] dr = { -1, 1, 0, 0 };
	static int[] dc = { 0, 0, -1, 1 };
	static int N, L, R;
	static int[][] map;
	static boolean[][] visited;
	static List<Point> contryList;
	static boolean flag;

	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());
			}
		}

		int result = 0;
		while (true) {
			flag = false;
			visited = new boolean[N][N];

			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					if (!visited[i][j]) {
						bfs(new Point(i, j));
						move();
					}
				}
			}

			if (!flag) {
				System.out.println(result);
				break;
			}

			result++;
		}

	}

	// 인구 이동
	private static void move() {
		int population = 0;
		for (Point p : contryList) {
			population += map[p.x][p.y];
		}
		population = (int) population / contryList.size();
		for (Point p : contryList) {
			map[p.x][p.y] = population;
		}
	}

	public static void bfs(Point point) {
		Queue<Point> q = new LinkedList<Point>();
		contryList = new ArrayList<Point>(); // 연합 국가 리스트
		visited[point.x][point.y] = true;
		contryList.add(point);
		q.offer(point);

		while (!q.isEmpty()) {
			Point now = q.poll();

			for (int d = 0; d < 4; d++) {
				int nr = now.x + dr[d];
				int nc = now.y + dc[d];

				if (isValid(nr, nc) && !visited[nr][nc] && Math.abs(map[now.x][now.y] - map[nr][nc]) >= L
						&& Math.abs(map[now.x][now.y] - map[nr][nc]) <= R) {
					flag = true;
					visited[nr][nc] = true;
					Point np = new Point(nr, nc);
					contryList.add(np);
					q.offer(np);
				}
			}
		}
	}

	public static boolean isValid(int r, int c) {
		return 0 <= r && r < N && 0 <= c && c < N;
	}
}

 


 

3. 정답 코드

import java.util.*;
 
public class Main {
    
    static int n, l, r;
    static int[][] board;
    static boolean[][] visited;
    static int[] dx = {0, 1, 0, -1};
    static int[] dy = {1, 0, -1, 0};
    static ArrayList<Node> list; //인구 이동이 필요한 노드 리스트
 
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);    
 
        n = scan.nextInt();
        l = scan.nextInt();
        r = scan.nextInt();
        
        board = new int[n][n];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                board[i][j] = scan.nextInt();
            }
        }
        
        System.out.println(move());
    }
    
    public static int move() { //더 이상 인구이동이 일어나지 않을 때까지 반복
        int result = 0;
        while(true) {
            boolean isMove = false;
            visited = new boolean[n][n];
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < n; j++) {
                    if(!visited[i][j]) {
                        int sum = bfs(i, j); //bfs탐색으로 열릴 수 있는 국경선 확인 하며 인구 이동할 총 인구수 반환
                        if(list.size() > 1) {
                            changePopulation(sum); //열린 국경선 내의 노드들 인구 변경
                            isMove = true;
                        }    
                    }
                }
            }
            if(!isMove) return result;;
            result++;
        }
    }
    
    public static int bfs(int x, int y) {
        Queue<Node> q = new LinkedList<>();
        list = new ArrayList<>();
        
        q.offer(new Node(x, y));
        list.add(new Node(x, y));
        visited[x][y] = true;
        
        int sum = board[x][y];
        while(!q.isEmpty()) {
            Node current = q.poll();
            
            for(int i = 0; i < 4; i++) {
                int nx = current.x + dx[i];
                int ny = current.y + dy[i];
                if(nx >= 0 && ny >= 0 && nx < n && ny < n && !visited[nx][ny]) {
                    int diff = Math.abs(board[current.x][current.y] - board[nx][ny]);
                    if(l <= diff && diff <= r) {
                        q.offer(new Node(nx, ny));
                        list.add(new Node(nx, ny));
                        sum += board[nx][ny];
                        visited[nx][ny] = true;
                    }        
                }
            }
        }
        return sum;
    }
    
    public static void changePopulation(int sum) {
        int avg = sum / list.size();
        for(Node n : list) {
            board[n.x][n.y] = avg;
        }
    }
    
    public static class Node {
        int x; 
        int y;
        
        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}

 


 

4. 배운 점

- 틀린 문제 다시 많이 풀어보자.

'Algorithm > Problem' 카테고리의 다른 글

사회망 서비스(SNS)(BJ_G3_2533)  (0) 2024.06.06
불!(BJ_G3_4179)  (0) 2024.05.27
불(BJ_G4_5427)  (0) 2024.04.17
치즈(BJ_G4_2636)  (0) 2024.04.13
파티 (BJ_G3_1238)  (0) 2024.04.08