본문 바로가기
Problem Solving/삼성 SW 역량 테스트 기출

백준 16234 : 인구 이동

by Libi 2021. 8. 3.
반응형

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

 

16234번: 인구 이동

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

www.acmicpc.net

[ 문제풀이 ]

이번에도 역시 주어진 조건대로 시뮬레이션하는 문제이다. 골드 5의 난이도답게 정말 간단한 문제이다.

dfs를 통해 경계선을 공유한 영역들을 나눠주기만 한다면 쉽게 해결할 수 있을 것이다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

public class Main {

	static int N, L, R, answer, check, count;
	static int[][] A, visit;
	static boolean mark;
	static List<Integer> list;

	static int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		L = Integer.parseInt(st.nextToken());
		R = Integer.parseInt(st.nextToken());

		A = new int[N][N];
		visit = new int[N][N];
		list = new ArrayList<>();
		for (int i = 0; i < N; ++i) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < N; ++j) {
				A[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		do {
			//변수들 초기화
			init();
			//경계선을 open
			openBoundary();
			//각 경계선에 속하는 인구 이동
			movePeople();
			//인구 이동이 발생했다면
			if (mark) answer++;
		} while(mark);

		bw.write(answer + "\n");
		bw.flush();bw.close();br.close();
	}

	public static void init() {
		mark = false;
		check = 1;
		list.clear();
		for (int i = 0; i < N; ++i) {
			Arrays.fill(visit[i], 0);
		}
	}

	public static void openBoundary() {
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				if (visit[i][j] != 0) continue;
				//방문하지 않은 영역을 dfs를 돌려 국경선을 열 수 있는 영역을 체크 후
				//(방문한 영역의 인구 총합 / 방문한 영역의 개수)를 리스트에 넣어줌
				list.add(dfs(i, j) / count);
				check++;
				count = 0;
			}
		}
	}

	public static int dfs(int y, int x) {
		int sum = A[y][x];
		count++;
		visit[y][x] = check;

		for (int d = 0; d < 4; ++d) {
			int ny = y + dir[d][0];
			int nx = x + dir[d][1];

			if (ny < 0 || nx < 0 || ny >= N || nx >= N) continue;
			if (visit[ny][nx] != 0) continue;

			int diff = Math.abs(A[y][x] - A[ny][nx]);
			//인접한 영역의 인구 수 차이가 L이상 R이하라면 dfs를 돌려 방문 체크해줌
			if (diff >= L && diff <= R) {
				sum += dfs(ny, nx);
				mark = true;
			}
		}
		return sum;
	}

	public static void movePeople() {
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				if (visit[i][j] == 0) continue;
				//방문한 영역이라면 인구를 분배
				A[i][j] = list.get(visit[i][j] - 1);
			}
		}
	}
}

 

 

반응형

'Problem Solving > 삼성 SW 역량 테스트 기출' 카테고리의 다른 글

백준 17144 : 미세먼지 안녕!  (0) 2021.08.03
백준 16235 : 나무 재테크  (0) 2021.08.03
백준 5373 : 큐빙  (0) 2021.08.02
백준 15686 : 치킨 배달  (0) 2021.08.02
백준 15685 : 드래곤 커브  (0) 2021.08.02

댓글