developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 운영체제인터럽트
  • 삼성코테구현문제추천
  • ARIMA모형
  • 시계열분석
  • 코테파이썬
  • 데이터분석
  • 통계학
  • MA모형
  • 삼성코테파이썬준비
  • 백준파이썬풀이
  • 시계열
  • c++디자인패턴
  • Arima
  • 통계분석
  • SW역량테스트파이썬
  • AR모형
  • c++ 빌더 패턴
  • 삼성코테자바꿀팁
  • 삼성코테구현풀이
  • 카카오코테
  • BOJ파이썬풀이
  • 삼성코테자바풀이
  • SW역량테스트파이썬풀이
  • 카카오코테java풀이
  • 삼성코테파이썬풀이
  • 삼성코테파이썬
  • 삼성코테준비
  • 삼성코테기출자바풀이
  • 삼성코테자바준비
  • 삼성코테기출

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

BOJ - 상어 중학교 21609번 (JAVA)

2022. 4. 30. 14:54

❓ 문제 - 백준 상어 중학교 21609번 - JAVA 풀이법

 

출처 

(https://www.acmicpc.net/problem/21609)

 

21609번: 상어 중학교

상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록

www.acmicpc.net

 

 

📝 문제해결법

1. 이 문제는 구현+BFS으로 풀었다.

  • Block 객체로 한 블록 그룹의 정보를 저장한다. x, y는 기준 블록의 위치, size는 블록의 사이즈, mu_cnt는 무지개 블록의 갯수이다. 
  • 2차원 배열 0행 0열부터 쭉 접근하면서 BFS를 통해 최대 길이의 블록 그룹을 찾는다. 만약 찾은 블록들이 그룹의 크기가 2이상이면 블록 그룹 list에 블록 정보를 넣는다. visited 배열은 블록 그룹이 연결된 것들의 무지개 블록을 제외한 것의 방문처리를 하는 것이고 visited2는 bfs 내에서 방문처리를 위해 사용하는 배열이다.
  • 무지개 블록은 다른 색깔이 다른 블록 그룹에 포함될 수 있기 때문에 visited 배열에서는 방문처리를 안 해줘야 한다.
  • 그리고 블록 그룹 중에서 길이가 가장 큰, 그리고 길이가 같다면 무지개 블록의 갯수가 많은, 그리고 무지개 블록 개수가 많다면, 기준 블록의 행이 큰, 행이 같다면 열이 큰 순으로 정렬한다. 그리고 해당 기준으로 뽑힌 하나의 블록 그룹이 존재하지 않는다면 while을 빠져나오고, 블록 그룹이 존재한다면 해당 블록 그룹을 제거 처리 해줘야 한다.
  • 블록 그룹을 제거 처리하기 위해 기준 블록에 대한 정보를 바탕으로 bfs2() 메소드로 제거 처리를 진행해준다. 제거된 블록은 -2로 표기한다.
  • 블록 그룹이 제거되었다면 중력처리를 위해 맨 밑 행부터 밑으로 끌어 당기는 작업을 수행한다. 만약 현재 보는 행이 비어있는 상태(-2)라면 위에 자기 자신으로 끌어당길 블록들을 위로 올라가면서 찾고 검은 블록이 아닌 다른 블록을 찾는다면 현재 행으로 위치 시켜주고 끌어당기는 위치 부분은 비어줌처리(-2) 해준다.
  • 그리고 moving 함수를 통해 90도 반시계 방향으로 전환한다.

 

 

💻 소스코드

// BOJ - 상어 중학교 (21609번)
// BFS + 구현

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.concurrent.LinkedBlockingDeque;

public class Main_21609 {
	public static int n, m;
	public static int[][] map;
	public static boolean[][] visited;
	public static int[] dx = {-1, 1, 0, 0};
	public static int[] dy = {0, 0, -1, 1};
	public static class Block implements Comparable<Block>{
		int x;
		int y;
		int size;
		int mu_cnt;
		public Block(int x, int y, int size, int mu_cnt) {
			this.x = x;
			this.y = y;
			this.size = size;
			this.mu_cnt = mu_cnt;
		}
		@Override
		public int compareTo(Block o) {
			if(this.size == o.size) {
				if(this.mu_cnt == o.mu_cnt) {
					if(this.x == o.x) {
						return -(this.y - o.y);
					}
					return -(this.x - o.x);
				}
				return -(this.mu_cnt-o.mu_cnt);
			}
			return -(this.size - o.size);
		}
	}
	public static ArrayList<Block> list;
	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());
		m = Integer.parseInt(st.nextToken());
		map = new int[n][n];
		visited = new boolean[n][n];
		list = new ArrayList<>();
		
		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 score = 0;
		
		while(true) {
			// 최대 길이 블록 그룹 찾기
			visited = new boolean[n][n];
			for(int i=0;i<n;i++) {
				for(int j=0;j<n;j++) {
					if(!visited[i][j] && map[i][j] > 0) {
						bfs(i, j, map[i][j]);
					}
				}
			}
			
			Collections.sort(list);
			// 블록 그룹 제거
			if(list.size() == 0) {
				break;
			}
			
			
			Block b = list.get(0);
		
			bfs2(b.x, b.y);
			score += b.size * b.size;
			
			
			// 중력
			fall();
			
			// 반시계 회전
			moving();
			
			// 중력
			fall();
		
			list.clear();
		}
		
		
		

		
		System.out.println(score);
	}
	
	public static void print() {
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				System.out.print(map[i][j] +" ");
			}
			System.out.println();
		}
		System.out.println();
	}
	
	public static void moving() {
		int[][] temp = new int[n][n];
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				temp[i][j] = map[j][n-i-1];
			}
		}
		map = temp;
	}
	
	public static void fall() {
		for(int j=0;j<n;j++) {
			for(int i=n-1;i>=1;i--) {
				if(map[i][j] != -2) continue;
				int nx = i;
				while(true) {
					nx -= 1;
					if(nx < 0) break;
					if(map[nx][j] == -1) break;
					if(map[nx][j] != -2) {
						map[i][j] = map[nx][j];
						map[nx][j] = -2;
						break;
					}
				}
			}
		}
	}
	
	public static void bfs2(int x, int y) {
		Queue<int[]> q = new LinkedList<int[]>();
		q.add(new int[] {x, y});
		int c = map[x][y];
		map[x][y] = -2;
		while(!q.isEmpty()) {
			int[] arr = q.poll();
			for(int d=0;d<4;d++) {
				int nx = arr[0] + dx[d];
				int ny = arr[1] + dy[d];
				if(0 <= nx && nx < n && 0 <= ny && ny < n) {
					if(map[nx][ny] == 0 || map[nx][ny] == c) {
						map[nx][ny] = -2;
						q.add(new int[] {nx, ny});
					}
				}
			}
		}
		
	}
	
	public static void bfs(int x, int y, int c) {
		boolean[][] visited2 = new boolean[n][n];
		
		visited[x][y] = true;
		visited2[x][y] = true;
		Queue<int[]> q = new LinkedList<>();
		int size = 1;
		int mu_cnt = 0;
		q.add(new int[] {x, y});
		
		while(!q.isEmpty()) {
			int[] arr = q.poll();
			for(int d=0;d<4;d++) {
				int nx = arr[0] + dx[d];
				int ny = arr[1] + dy[d];
				if(0 <= nx && nx < n && 0 <= ny && ny < n) {
					if(map[nx][ny] == -1) continue;
					
					if(!visited2[nx][ny]) {
						if(map[nx][ny] == 0) {
							mu_cnt++;
							size++;
							visited2[nx][ny] = true;
							q.add(new int[] {nx, ny});
						} else if(map[nx][ny] == c) {
							size++;
							visited[nx][ny] = true;
							visited2[nx][ny] = true;
							q.add(new int[] {nx, ny});
							
						}
					}
				}
			}
		}
		
		if(size == 1) {
			return;
		} else {
			list.add(new Block(x, y, size, mu_cnt));
		}
		
	}

}

 

 

 

 

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

BOJ - 마법사 상어와 블리자드 21611번 (JAVA)  (0) 2022.04.30
BOJ - 마법사 상어와 비바라기 21610번 (JAVA)  (0) 2022.04.30
BOJ - 마법사 상어와 파이어스톰 20058번 (JAVA)  (0) 2022.04.30
BOJ - 마법사 상어와 토네이도 20057번 (JAVA)  (0) 2022.04.30
BOJ - 마법사 상어와 파이어볼 20056번 (JAVA)  (0) 2022.04.30
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 마법사 상어와 블리자드 21611번 (JAVA)
    • BOJ - 마법사 상어와 비바라기 21610번 (JAVA)
    • BOJ - 마법사 상어와 파이어스톰 20058번 (JAVA)
    • BOJ - 마법사 상어와 토네이도 20057번 (JAVA)
    developer-ellen
    developer-ellen

    티스토리툴바