🌞Algorithm/πŸ”₯Baekjoon

[Baekjoon] 2468_μ•ˆμ „ μ˜μ—­

λΏŒμ•Ό._. 2022. 4. 1. 15:30

Silver I

문제(좜처: https://www.acmicpc.net/problem/2468)

<μ•ˆμ „ μ˜μ—­>

문제 

 

μž¬λ‚œλ°©μž¬μ²­μ—μ„œλŠ” λ§Žμ€ λΉ„κ°€ λ‚΄λ¦¬λŠ” μž₯λ§ˆμ² μ— λŒ€λΉ„ν•΄μ„œ λ‹€μŒκ³Ό 같은 일을 κ³„νšν•˜κ³  μžˆλ‹€. λ¨Όμ € μ–΄λ–€ μ§€μ—­μ˜ 높이 정보λ₯Ό νŒŒμ•…ν•œλ‹€. κ·Έλ‹€μŒμ— κ·Έ 지역에 λ§Žμ€ λΉ„κ°€ 내렸을 λ•Œ 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ΄ μ΅œλŒ€λ‘œ λͺ‡ κ°œκ°€ λ§Œλ“€μ–΄μ§€λŠ” μ§€λ₯Ό μ‘°μ‚¬ν•˜λ €κ³  ν•œλ‹€. μ΄λ•Œ, 문제λ₯Ό κ°„λ‹¨ν•˜κ²Œ ν•˜κΈ° μœ„ν•˜μ—¬, μž₯λ§ˆμ² μ— λ‚΄λ¦¬λŠ” λΉ„μ˜ 양에 따라 μΌμ •ν•œ 높이 μ΄ν•˜μ˜ λͺ¨λ“  지점은 물에 μž κΈ΄λ‹€κ³  κ°€μ •ν•œλ‹€.

μ–΄λ–€ μ§€μ—­μ˜ 높이 μ •λ³΄λŠ” ν–‰κ³Ό μ—΄μ˜ 크기가 각각 N인 2차원 λ°°μ—΄ ν˜•νƒœλ‘œ μ£Όμ–΄μ§€λ©° λ°°μ—΄μ˜ 각 μ›μ†ŒλŠ” ν•΄λ‹Ή μ§€μ μ˜ 높이λ₯Ό ν‘œμ‹œν•˜λŠ” μžμ—°μˆ˜μ΄λ‹€. 예λ₯Ό λ“€μ–΄, λ‹€μŒμ€ N=5인 μ§€μ—­μ˜ 높이 정보이닀.

 

이제 μœ„μ™€ 같은 지역에 λ§Žμ€ λΉ„κ°€ λ‚΄λ €μ„œ 높이가 4 μ΄ν•˜μΈ λͺ¨λ“  지점이 물에 μž κ²Όλ‹€κ³  ν•˜μž. 이 κ²½μš°μ— 물에 μž κΈ°λŠ” 지점을 νšŒμƒ‰μœΌλ‘œ ν‘œμ‹œν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€. 

물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ΄λΌ 함은 물에 μž κΈ°μ§€ μ•ŠλŠ” 지점듀이 μœ„, μ•„λž˜, 였λ₯Έμͺ½ ν˜Ήμ€ μ™Όμͺ½μœΌλ‘œ 인접해 있으며 κ·Έ 크기가 μ΅œλŒ€μΈ μ˜μ—­μ„ λ§ν•œλ‹€. μœ„μ˜ κ²½μš°μ—μ„œ 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ€ 5κ°œκ°€ λœλ‹€(κΌ­μ§“μ μœΌλ‘œλ§Œ λΆ™μ–΄ μžˆλŠ” 두 지점은 μΈμ ‘ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  μ·¨κΈ‰ν•œλ‹€). 

λ˜ν•œ μœ„μ™€ 같은 μ§€μ—­μ—μ„œ 높이가 6 μ΄ν•˜μΈ 지점을 λͺ¨λ‘ 잠기게 λ§Œλ“œλŠ” λ§Žμ€ λΉ„κ°€ 내리면 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ€ μ•„λž˜ κ·Έλ¦Όμ—μ„œμ™€ 같이 λ„€ κ°œκ°€ 됨을 확인할 수 μžˆλ‹€. 

이와 같이 μž₯λ§ˆμ² μ— λ‚΄λ¦¬λŠ” λΉ„μ˜ 양에 λ”°λΌμ„œ 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ˜ κ°œμˆ˜λŠ” λ‹€λ₯΄κ²Œ λœλ‹€. μœ„μ˜ μ˜ˆμ™€ 같은 μ§€μ—­μ—μ„œ λ‚΄λ¦¬λŠ” λΉ„μ˜ 양에 λ”°λ₯Έ λͺ¨λ“  경우λ₯Ό λ‹€ 쑰사해 보면 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ˜ 개수 μ€‘μ—μ„œ μ΅œλŒ€μΈ κ²½μš°λŠ” 5 μž„μ„ μ•Œ 수 μžˆλ‹€. 

μ–΄λ–€ μ§€μ—­μ˜ 높이 정보가 μ£Όμ–΄μ‘Œμ„ λ•Œ, μž₯λ§ˆμ² μ— 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ˜ μ΅œλŒ€ 개수λ₯Ό κ³„μ‚°ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. 

 

 

μž…λ ₯

 

첫째 μ€„μ—λŠ” μ–΄λ–€ 지역을 λ‚˜νƒ€λ‚΄λŠ” 2차원 λ°°μ—΄μ˜ ν–‰κ³Ό μ—΄μ˜ 개수λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 수 N이 μž…λ ₯λœλ‹€. N은 2 이상 100 μ΄ν•˜μ˜ μ •μˆ˜μ΄λ‹€. λ‘˜μ§Έ 쀄뢀터 N개의 각 μ€„μ—λŠ” 2차원 λ°°μ—΄μ˜ 첫 번째 ν–‰λΆ€ν„° N번째 ν–‰κΉŒμ§€ μˆœμ„œλŒ€λ‘œ ν•œ ν–‰μ”© 높이 정보가 μž…λ ₯λœλ‹€. 각 μ€„μ—λŠ” 각 ν–‰μ˜ 첫 번째 μ—΄λΆ€ν„° N번째 μ—΄κΉŒμ§€ N개의 높이 정보λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μžμ—°μˆ˜κ°€ λΉˆμΉΈμ„ 사이에 두고 μž…λ ₯λœλ‹€. λ†’μ΄λŠ” 1 이상 100 μ΄ν•˜μ˜ μ •μˆ˜μ΄λ‹€.

 

 

좜λ ₯ 

 

첫째 쀄에 μž₯λ§ˆμ² μ— 물에 μž κΈ°μ§€ μ•ŠλŠ” μ•ˆμ „ν•œ μ˜μ—­μ˜ μ΅œλŒ€ 개수λ₯Ό 좜λ ₯ν•œλ‹€.

 

 

문제 풀이

   - my solution (Python)

import sys
from collections import deque

def safe(visited, a,b):
    dx=[-1,1,0,0] # μƒν•˜μ’Œμš°
    dy=[0,0,-1,1]
    queue=deque([[a,b]])

    while queue:
        temp=queue.popleft()
        for i in range(4):
            x=temp[0]+dx[i]
            y=temp[1]+dy[i]
            if x>=0 and x<len(visited) and y>=0 and y<len(visited[0]): # μ§€μ—­ λ²”μœ„ μ•ˆ
                if visited[x][y]==0: # 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜μœΌλ©΄
                    queue.append([x,y])
                    visited[x][y]=1

if __name__=='__main__':
    n=int(input())

    arr=[]
    height=[]
    for i in range(n):
        temp=list(map(int, sys.stdin.readline().split()))
        arr.append(temp)
        height+=temp

    height=set(height) # μ§€μ—­μ˜ 높이

    answer=1 # 전체 지역이 물에 μž κΈ°μ§€ μ•Šμ€ 경우
    for i in height:
        cnt = 0
        visited=[[0]*n for j in range(n)]
        for j in range(n):
            for k in range(n):
                if arr[j][k]<=i: # i 높이 μ΄ν•˜ 지점
                    visited[j][k]=1 # λ°©λ¬Έ o
        for j in range(n):
            for k in range(n):
                if visited[j][k]==0: # 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜μœΌλ©΄
                    cnt+=1 # μ•ˆμ „ν•œ μ˜μ—­ 개수
                    safe(visited, j, k)
        if answer<cnt: # μ•ˆμ „ν•œ μ˜μ—­μ˜ μ΅œλŒ€ 개수
            answer=cnt
    print(answer)

 

- my solution (JAVA)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;

public class _2468_μ•ˆμ „μ˜μ—­ {
	static void safe(int visited[][], int a, int b) {
		int dx[]= {-1,1,0,0}; // μƒν•˜μ’Œμš°
		int dy[]= {0,0,-1,1};
		
		Queue<int []> queue=new LinkedList<>();
		queue.add(new int[]{a,b});
		
		while(queue.size()!=0) {
			int temp[]=queue.poll();
			for(int i=0; i<4; i++) {
				int x=temp[0]+dx[i];
				int y=temp[1]+dy[i];
				if(x>=0 && x<visited.length && y>=0 && y<visited[0].length) {
					// μ§€μ—­ λ²”μœ„ μ•ˆ
					if(visited[x][y]==0) { // 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜μœΌλ©΄
						queue.add(new int[] {x,y});
						visited[x][y]=1; // λ°©λ¬Έ
					}
				}
			}
		}
	}
	
	public static void main(String[] args) throws IOException{
		BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
		
		int n= Integer.parseInt(bf.readLine());
		
		int arr[][]=new int[n][n];
		HashSet<Integer> set=new HashSet<>();
		
		for(int i=0; i<n; i++) { // 높이 정보 μ €μž₯
			String str=bf.readLine();
			for(int j=0; j<n; j++) {
				int temp=Integer.parseInt(str.split(" ")[j]);
				arr[i][j]=temp;
				set.add(temp); // μ§€μ—­μ˜ 높이
			}
		}
		
		int answer=1; // 전체 지역이 물에 μž κΈ°μ§€ μ•Šμ€ 경우 -> 1
		
		for(int i:set) {
			int cnt=0;
			int visited[][]=new int[n][n];
			for(int j=0; j<n; j++) {
				for(int k=0; k<n; k++) {
					if(arr[j][k]<=i) { // i 높이 μ΄ν•˜ 지점
						visited[j][k]=1; // λ°©λ¬Έ o
					}
				}
			}
			for(int j=0; j<n; j++) {
				for(int k=0; k<n; k++) {
					if(visited[j][k]==0) { // 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜μœΌλ©΄
						cnt+=1; // μ•ˆμ „ν•œ μ˜μ—­ 개수
						safe(visited,j,k);
					}
				}
			}
			if(answer<cnt) { // μ•ˆμ „ν•œ μ˜μ—­μ˜ μ΅œλŒ€ 개수
				answer=cnt;
			}
		}
		System.out.println(answer);
	}
}

 

μ£Όμ–΄μ§„ μ§€μ—­μ˜ 높이듀을 μ €μž₯ν•œ ν›„ λͺ¨λ“  경우의 수λ₯Ό λ”°μ Έλ³Έλ‹€.

각 높이 μ΄ν•˜μΈ 지점을 λͺ¨λ‘ 잠기게 될 λ•Œ μ•ˆμ „ν•œ μ˜μ—­μ˜ 개수λ₯Ό 찾도둝 ν•΄μ€€λ‹€.

λͺ¨λ“  경우의 수λ₯Ό λ”°μ Έ κ°€μž₯ λ§Žμ€ μ•ˆμ „ν•œ μ˜μ—­μ˜ 수λ₯Ό λ‹΅μœΌλ‘œ 좜λ ₯ν•΄μ€€λ‹€.

 

  • safe
    : dx, dy = μƒν•˜μ’Œμš° 탐색
    : queueκ°€ 빌 λ•ŒκΉŒμ§€ 반볡 -> 제일 처음 값을 pop -> μƒν•˜μ’Œμš° ν™•μΈν•˜μ—¬ μ§€μ—­ λ²”μœ„ μ•ˆμ΄λ©° 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ queue에 μΆ”κ°€ 및 λ°©λ¬Έ check
  • main
    : n μž…λ ₯
    : arr = μ§€μ—­ 높이 정보 μ €μž₯
    : height = set을 ν™œμš©ν•˜μ—¬ μ€‘λ³΅λ˜μ§€ μ•Šκ²Œ 높이 μ €μž₯
    : answer = 전체 지역이 물에 μž κΈ°μ§€ μ•Šμ€ 경우 -> 1둜 μ„€μ •
    : height => 높이 μ΄ν•˜ 지점을 λ°©λ¬Έν•œ κ²ƒμœΌλ‘œ ν‘œμ‹œ => 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜μœΌλ©΄ μ•ˆμ „ν•œ μ˜μ—­ 개수(cnt) +1, ν•¨μˆ˜ 호좜 => answer보닀 cnt 값이 더 크면 answer= cnt
    : answer 좜λ ₯

 


μƒκ°πŸ€”

 

λ¬Έμ œμ—μ„œ 아무 지역도 물에 μž κΈ°μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€ μ΄ 뢀뢄을 λͺ‡ λ²ˆμ΄λ‚˜ λ΄€μœΌλ©΄μ„œ 반레λ₯Ό μ°Ύμ•„λ‚΄μ§€ λͺ»ν–ˆλ‹€.

μ € 말 λœ»μ€ 아무 지역도 물에 μž κΈ°μ§€ μ•Šμ•˜μ„ λ•Œ μ•ˆμ „ν•œ μ§€μ—­μ˜ κ°œμˆ˜κ°€ 1이 될 수 μžˆλ‹€λŠ” λ§μ΄μ—ˆλ‹€.