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)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

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

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

BOJ - 온풍기 안녕! 23289번 (JAVA)
알고리즘/알고리즘문풀

BOJ - 온풍기 안녕! 23289번 (JAVA)

2022. 4. 30. 16:17

❓ 문제 - 백준 온풍기 안녕! 23289번 - JAVA 풀이법

 

출처 

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

 

23289번: 온풍기 안녕!

유난히 추운 날씨가 예상되는 이번 겨울을 대비하기 위해 구사과는 온풍기를 설치하려고 한다. 온풍기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기

www.acmicpc.net

 

 

 

📝 문제해결법

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

  • 벽에 대한 정보를 ArryList 2차원 배열인 map_wall로 관리하였다. 만약 i, j행에 0이라는 숫자가 있으면 (i, j)위치의 윗부분에 벽이 있다는 것이고, 1이라는 숫자가 존재하면 (i, j)위치에 오른쪽부분에 벽이 있다는 의미이다.
  • 온풍기에서 나오는 바람은 각 방향에 맞춰 3방향으로 영향을 줄 수 있으며 만약 그 방향에 맞춰 이동할 곳에 벽이 존재한다면 바람이 이동하지 못한다.

 

  • 각 이동 방향에 맞춰 이동할 수 있는 부분이 빨간색이고 해당 곳에 이동을 하기 위해서는 위와 같이 현재 위치(x, y)에서 각 이동할 방향에 맞춰 벽이 존재하는지를 탐색해야한다. 이것을 check_wall이라는 3차원 배열을 통해 구현하였으며 각 방향(동, 서, 북, 남) 의 방향에 맞춰 벽이 있는지 확인할 수 있는 수치를 넣어 x, y로 nx, ny를 구해 범위를 넘지 않는 범위에서 벽이 존재하는지 체크하였다.
  • 현재 위치에서 이동할 방향은 check_dir에 넣었고 각 동, 서, 북, 남의 인덱스에 맞춰 대각선, 직선방향으로 이동할 방향을 넣었다. 만약 이동할 곳이 격자 범위를 넘는 곳이라면 continue 만약 이동할 수 있다면 check_wall이라는 배열을 활용해서 해당 방향으로 이동하는데 체크해야할 벽이 존재하는지를 파악한 후, 벽이 존재하지 않는다면 이동 처리한다.
  • 온도 조절 처리도 위의 check_dir을 활용하여 동, 서, 북, 남으로 이동할 때 어느 부분이 벽의 존재 위치를 파악해서 온도 조절이 되는지 안되는지 파악해주는 것이 특징이다.

 

2. 느낀점

  • 세상 빡구현이다... 처음에 동,서,북,남, 대각선들을 체크할 때 벽의 확인 부분이 일관된줄 알고 구현했는데 알고 보니 방향에 따라 이동 위치의 벽의 확인 위치도 다 달라져서... 그냥 맞춰서 다 구현할 수 밖에 없었다 ^_^..
  • 깔끔한 코드는 아니지만,,, 그래도 어느정도 코드 다이어트를 할 수 있을만큼 했다... ㅎㅎ
  • 이해 안 가는 분들은,, 댓글 달아주세유,,

 

 

💻 소스코드

// BOJ - 온풍기 안녕!
// 구현

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


public class Main_23289 {
	public static int r, c, k;
	public static int[][] map;
	public static int[][] heat;
	// 동, 서, 북, 남, 오위, 오아, 왼위, 왼아
	public static int[] dx = {0, 0, 0, -1 ,1, -1, 1, -1, 1};
	public static int[] dy = {0, 1, -1, 0, 0, 1, 1, -1, -1};
	
	public static int[][] check_dir = {{}, {5, 1, 6}, {7, 2, 8}, {7, 3, 5}, {8, 4, 6}};
	
	public static int[][][][] check_wall = {{}, 
			{{{0, 0, 0}, {-1, 0, 1}}, {{0, 0, 1}}, {{1, 0, 0}, {1, 0, 1}}}, 
			{{{-1, -1, 1}, {0, 0, 0}}, {{0, -1, 1}}, {{1, 0, 0}, {1, -1, 1}}}, 
			{{{0, -1, 1}, {0, -1, 0}}, {{0, 0, 0}}, {{0, 0, 1}, {0, 1, 0}}}, 
			{{{0, -1, 1}, {1, -1 ,0}}, {{1, 0, 0}}, {{0, 0, 1}, {1, 1, 0}}}};
	public static ArrayList<Node> machine;
	public static ArrayList<Integer>[][] map_wall;
	public static class Node {
		int x;
		int y;
		int dir;
		int heat;
		public Node(int x, int y, int dir) {
			this.x = x;
			this.y = y;
			this.dir = dir;
		}
		
		public Node(int x, int y, int dir, int heat) {
			this.x = x;
			this.y = y;
			this.dir = dir;
			this.heat = heat;
		}
	}

	
 	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		r = Integer.parseInt(st.nextToken());
		c = Integer.parseInt(st.nextToken());
		k = Integer.parseInt(st.nextToken());
		map = new int[r][c];
		map_wall = new ArrayList[r][c];
		machine = new ArrayList<>();
		heat = new int[r][c];
		
		for(int i=0;i<r;i++) {
			st = new StringTokenizer(br.readLine(), " ");

			for(int j=0;j<c;j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
				map_wall[i][j] = new ArrayList<Integer>();
				if(map[i][j] >=1 && map[i][j] <=4) {
					machine.add(new Node(i, j, map[i][j]));
				}
			}
		}
		
		int w = Integer.parseInt(br.readLine());
		for(int i=0;i<w;i++) {
			st = new StringTokenizer(br.readLine()," ");
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			int t = Integer.parseInt(st.nextToken());
			map_wall[x-1][y-1].add(t);
		}
		
		int eat = 0;
		
		while(eat <= 100) {
			for(int i=0;i<machine.size();i++) {
				Node node = machine.get(i);
				int x = node.x + dx[node.dir];
				int y = node.y + dy[node.dir];
				boolean[][] visited = new boolean[r][c];
				if(is_chk(x, y)) {
					visited[x][y] = true;
					Queue<Node> q = new LinkedList<>();
					q.add(new Node(x, y, node.dir, 5));
					while(!q.isEmpty()) {
						Node nd = q.poll();
						heat[nd.x][nd.y] += nd.heat;
					
						outer:for(int d=0;d<3;d++) {
							int dir = check_dir[nd.dir][d];
					
							int ch_x = nd.x + dx[dir];
							int ch_y = nd.y + dy[dir];
							
							if(!is_chk(ch_x, ch_y)) continue;
							if(visited[ch_x][ch_y]) continue;
							
							for(int n=0;n<check_wall[nd.dir][d].length;n++) {
								int nx = nd.x + check_wall[nd.dir][d][n][0];
								int ny = nd.y + check_wall[nd.dir][d][n][1];
					
								if(is_chk(nx, ny)) {
									for(int a=0;a<map_wall[nx][ny].size();a++) {
										if(map_wall[nx][ny].get(a) == check_wall[nd.dir][d][n][2]) {
											
											continue outer;
										}
									}

								}
								
							}
							if(nd.heat >= 2) {
							
								visited[ch_x][ch_y] = true;
								q.add(new Node(ch_x, ch_y, nd.dir, nd.heat-1));
							}
						}
					
					}
				}
				
			
			}
		
			int[][] heat_copy = new int[r][c];
			for(int i=0;i<r;i++) {
				heat_copy[i] = heat[i].clone();
			}
			
			for(int i=0;i<r;i++) {
				for(int j=0;j<c;j++) {
					if(heat[i][j] == 0) continue;
					outer: for(int d=1;d<=4;d++) {
						int nx = i + dx[d];
						int ny = j + dy[d];
						if(!is_chk(nx, ny)) continue;
						if(heat[i][j] < heat[nx][ny]) continue;
						int chk_x = i + check_wall[d][1][0][0];
						int chk_y = j + check_wall[d][1][0][1];
						int chk_t = check_wall[d][1][0][2];
						if(is_chk(chk_x, chk_y)) {
							for(int a=0;a<map_wall[chk_x][chk_y].size();a++) {
								if(map_wall[chk_x][chk_y].get(a) == chk_t) {
									continue outer;
								}
							}
						}
						int diff = heat[i][j] - heat[nx][ny];
						if(heat_copy[i][j]  >= diff/4) {
							heat_copy[i][j] -= diff/4;
							heat_copy[nx][ny] += diff/4;
						}
					}
				}
			}
			
			for(int i=0;i<r;i++) {
				heat[i] = heat_copy[i].clone();
			}
	
	
			// 바깥쪽 칸의 온도 1씩 감소
			for(int j=0;j<c;j++) {
				if(heat[0][j] >= 1) heat[0][j]--;
				if(heat[r-1][j] >= 1) heat[r-1][j]--; 
			}
			
			for(int i=1;i<r-1;i++) {
				if(heat[i][0] >= 1) heat[i][0]--;
				if(heat[i][c-1] >= 1) heat[i][c-1]--; 
			}
			
			eat++;

			if(check()) {
				break;
			}
			
		}
		
		System.out.println(eat>=101?101:eat);
		
		

	}
 	
 	public static void print() {
 		for(int i=0;i<r;i++) {
 			for(int j=0;j<c;j++) {
 				System.out.print(heat[i][j] +" ");
 			}
 			System.out.println();
 		}
 		System.out.println();
 	}
 	
 	public static boolean check() {
 		for(int i=0;i<r;i++) {
 			for(int j=0;j<c;j++) {
 				if(map[i][j] == 5 && (heat[i][j] < k)) return false;
 			}
 		}
 		return true;
 	}
 	
 	public static boolean is_chk(int x, int y) {
 		if(x < 0 || x >= r || y < 0 || y >= c) return false;
 		return true;
 	}

}

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

BOJ - 우수 마을 1949번 (JAVA, Python)  (0) 2022.05.11
2021 KAKAO BLIND RECRUITMENT - 카드 짝 맞추기(JAVA)  (0) 2022.05.07
BOJ - 마법사 상어와 블리자드 21611번 (JAVA)  (0) 2022.04.30
BOJ - 마법사 상어와 비바라기 21610번 (JAVA)  (0) 2022.04.30
BOJ - 상어 중학교 21609번 (JAVA)  (0) 2022.04.30
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 우수 마을 1949번 (JAVA, Python)
    • 2021 KAKAO BLIND RECRUITMENT - 카드 짝 맞추기(JAVA)
    • BOJ - 마법사 상어와 블리자드 21611번 (JAVA)
    • BOJ - 마법사 상어와 비바라기 21610번 (JAVA)
    developer-ellen
    developer-ellen

    티스토리툴바