9_yoon
개발저장소
9_yoon
전체 방문자
오늘
어제
  • 분류 전체보기 (101)
    • 알고리즘 (52)
      • BJ (40)
      • 프로그래머스 (0)
      • SWEA (10)
      • JO (2)
    • 이론 공부 (7)
      • 네트워크 (2)
      • 알고리즘 (2)
      • Java (1)
      • Web (1)
      • 기타 (1)
    • 개발 공부 (35)
      • Project (1)
      • JavaScript (1)
      • Typescript (1)
      • Spring (12)
      • Java (2)
      • Next JS (7)
      • React (3)
      • Vue (1)
      • Web (5)
      • 기타 (2)
    • 기타 (7)
      • SSAFY (7)
      • 일상 (0)

인기 글

태그

  • 김영한 스프링
  • NextJS
  • 스프링
  • 싸피7기
  • SWEA
  • SSAFY
  • 노마드코더
  • 백준
  • React
  • 싸피

최근 글

티스토리

hELLO · Designed By 정상우.
9_yoon

개발저장소

[BJ] 백준 15683 감시 (JAVA)
알고리즘/BJ

[BJ] 백준 15683 감시 (JAVA)

2022. 2. 28. 21:41
728x90
반응형

문제

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

풀이 방법

cctv의 종류에 따라서 탐색해야하는 방향이 다른 문제이다. cctv가 탐색할 수 있는 공간을 다 탐색 후 cctv가 탐색하지 못한 사각지대를 찾아내면 된다. 복잡하긴 하지만 정리해서 구현만 한다면 그렇게 어렵지는 않은 문제다.
1. 클래스를 하나 만들어서 cctv의 종류에 따라서 탐색해야하는 인덱스를 미리 저장해놨다.
2. cctv의 종류에 따라서 방향이 다르기도 하지만 탐색 횟수도 다르다는걸 주의해야한다. 
ex) 1번은 90씩 회전해서 4번 탐색이 가능하지만, 2번은 2번만 탐색한다.
3. 탐색을 하면 나는 #으로 배열을 변경해줬고, 나중에 사각지대를 계산할 때는 0인 것들을 찾아서 카운팅 한 후 출력해줬다.

제출 코드

import java.io.*;
import java.util.*;

/*
 * 0 : 빈칸, 6: 벽 , 1~5: cctv 
 */
public class BJ_15683_감시 {
	public static int[][] move = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
	public static int N, M, min,  K; //K: cctv 개수
	public static List<CCTV> list; // cctv들의 정보 저장
	static class CCTV {
		int i, j; //cctv위치
		char type; //cctv타입
		List<int[]> dirs = new ArrayList<>(); // 방향에 맞게 탐색해야하는 방향들의 인덱스들을 저장
		public CCTV(char type, int i, int j) {
			this.type = type;
			this.i = i;
			this.j = j;
			setDir(type);
		}
		private void setDir(char type) { //cctv 타입에 맞춰서 탐색 방향의 인덱스를 넣어주기
			if (type == '1') {
				this.dirs.add(new int[] { 0 });
				this.dirs.add(new int[] { 1 });
				this.dirs.add(new int[] { 2 });
				this.dirs.add(new int[] { 3 });
			} else if (type == '2') {
				this.dirs.add(new int[] { 0, 1 });
				this.dirs.add(new int[] { 2, 3 });
			} else if (type == '3') {
				this.dirs.add(new int[] { 1, 2 });
				this.dirs.add(new int[] { 2, 0 });
				this.dirs.add(new int[] { 0, 3 });
				this.dirs.add(new int[] { 3, 1 });
			} else if (type == '4') {
				this.dirs.add(new int[] { 1, 2, 0 });
				this.dirs.add(new int[] { 2, 0, 3 });
				this.dirs.add(new int[] { 0, 3, 1 });
				this.dirs.add(new int[] { 3, 1, 2 });

			} else if (type == '5') {
				this.dirs.add(new int[] { 0, 1, 2, 3 });
			}
		}

	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		list = new ArrayList<CCTV>();

		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());

		char[][] map = new char[N][M];

		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < M; j++) {
				char ch = st.nextToken().charAt(0);
				map[i][j] = ch;
				if ('1' <= ch && '5' >= ch) { //cctv라면 list에 cctv정보 추가
					list.add(new CCTV(ch, i, j));
				}
			}
		}
		K = list.size(); //cctv개수
		min = N*M; //사각지대 개수 
		
		dfs(0, map);
		
		System.out.println(min);

	}

	private static void dfs(int cnt, char[][] map) { // 현재 몇번째 cctv인지

		// 기저 조건 cctv개수 만큼 다 탐색 하면 종료
		if (cnt == K) {
			// 탐색 완료 사각지대 개수 세기
			int count = 0; 
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < M; j++) {
					if(map[i][j]=='0') count++;
				}
			}
			min = Math.min(count, min);
			return;
		}

		// 방향 바꿔가면서 dfs 호출
		CCTV c = list.get(cnt); //cnt번째 cctv가져오기
		for (int i = 0; i < c.dirs.size(); i++) { //cctv의 방향이 가질 수 있는 개수 만큼 반복
			///이중배열 복사 
			char[][] nMap = new char[N][M];
			for (int j = 0; j < N; j++) {
				System.arraycopy(map[j], 0, nMap[j], 0, M);
			}

			searching(c.dirs.get(i), c.i, c.j, nMap); // cctv의 번호에 따른 방향들과 위치로 탐색 시작
			dfs(cnt + 1, nMap);
		}

	}

	private static void searching(int[] is, int i, int j, char[][] arr) {
		// is는 cctv의 방향'들' 1번이면 상 만 /2번이라면 상하 같이
		for (int z = 0; z < is.length; z++) { // 탐색해야하는 방향만큼 반복
			int p = i; 
			int q = j; 
			while (true) { 
				p= p + move[is[z]][0];
				q = q + move[is[z]][1];
				if (p >= 0 && p < N && q >= 0 && q < M) { //범위안
					if (arr[p][q] == '6') //벽이 있으면 brek;
						break;
					if (arr[p][q] == '0') //아무거도 없는 경우에만  #으로 변경
						arr[p][q] = '#';
				}else break; //범위 밖으로 나가면 break; 
				
			}
		}
	}
}

 

728x90
반응형
저작자표시 비영리 동일조건 (새창열림)

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

[BJ] 백준 2635 수 이어가기 (JAVA)  (1) 2022.03.02
[BJ] 백준 2304 창고 다각형 (JAVA)  (0) 2022.03.01
[BJ] 백준 1244 스위치 켜고 끄기 (JAVA)  (0) 2022.02.24
[BJ] 백준 10026 적록색약 (JAVA)  (0) 2022.02.23
[BJ] 백준 2669 직사각형 네 개의 합집합의 면적구하기 (JAVA)  (0) 2022.02.22
    '알고리즘/BJ' 카테고리의 다른 글
    • [BJ] 백준 2635 수 이어가기 (JAVA)
    • [BJ] 백준 2304 창고 다각형 (JAVA)
    • [BJ] 백준 1244 스위치 켜고 끄기 (JAVA)
    • [BJ] 백준 10026 적록색약 (JAVA)
    9_yoon
    9_yoon
    배울게 넘쳐나는 개발 세상에서 묵묵히 걸어가며 지식을 쌓는 신입 개발자

    티스토리툴바