광규니
광규니네
광규니
전체 방문자
오늘
어제
  • 분류 전체보기 (154)
    • 알고리즘 (100)
      • 알고리즘 개념 (2)
      • 문제 풀이 (96)
    • 주절주절 (19)
      • 자격증, 활동 후기 (4)
      • 전시회 후기 (3)
      • 이모저모 (2)
      • 회고 (3)
      • 뜨럼 (7)
    • 운영체제 (9)
    • 개발 지식 (9)
      • Apple Watch (4)
      • MySQL (2)
      • Eclipse (1)
      • XCode (1)
    • 네트워크 공부 (1)
    • 데이터베이스 공부 (5)
    • Java 공부 (7)
    • TMP (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 컴퓨터 사이언스
  • 애플워치 앱 만들기
  • 개념
  • 알고리즘
  • DP
  • 파이썬
  • 오블완
  • 다이나믹 프로그래밍
  • 드린이
  • 자바
  • 운영체제
  • 티스토리챌린지
  • 애플워치 앱
  • BFS
  • 합주
  • 구현
  • 프로그래머스
  • 백준
  • OS
  • BOJ

최근 댓글

최근 글

티스토리

250x250
hELLO · Designed By 정상우.
광규니

광규니네

알고리즘/문제 풀이

[Java/자바 백준 23290] 마법사 상어와 복제

2022. 3. 28. 21:32
반응형

풀이

문제를 읽다보면 주어진 조건이 너무 많다는 걸 알 수 있다..

 

우선 map 자체를 뭐로 선언해야할까 효율적일까 고민하다가

list로 선언하기에 삭제나 삽입할때 문제가 생길거 같아서

2차원 큐 형태로 물고기의 방향 값을 갖도록 설계했습니다.

 

1. copyFishmap() : 맵에 있는 물고기들 전부 복사하기 

map에 사이즈만큼 값을 copy[][]에  넣어줬습니다.

 

2. moveFish() : 물고기 이동

해당 맵 인덱스에 물고기가 있다면, 자신이 바라보는 방향부터 시작해서 반시계 45도로 탐색을 시작했습니다.

상어, 물고기 냄새, 격자 밖은 못가주게 해주었고 만약 8방향 탐색 후 모두 갈 수 없다면 제자리에 있도록 해주었습니다.

 

3. moveShark() : 상어 이동

순열을 이용했습니다. 저는 순열 부분에서 틀려서 시간이 꽤 오래 잡아먹었는데,

테스트케이스 4, 5번 틀리시는 분들은 방문했던 곳을 또다시 방문할 수 있게 바꿔보세요...

하지만 방문한 곳에 대해서 물고기가 있는 곳이라면 카운트를 중복으로 안하게끔 visitCnt를 만들어줘서 판단했습니다.

또한 순열을 사용한 이유는 상좌하우 탐색을 하기 위해서입니다. 

 

4. fishSmellDelete() : 물고기냄새 있는 칸 -1

4X4 smellMap 물고기 냄새를 저장해준걸 -1 씩 해줍니다.

 

5. insertCopyFish() : 복사해둔 물고기들을 삽입해줍니다.

1 과정에서 복사해둔 물고기들을 map에 다시 넣어줍니다.

 

조건들이 너무 많기에 하나라도 놓치면 디버깅 하기 빡신거 같아요..

상어 이동 과정에서 재방문 못할거라 생각해서 풀었는데, 그거때문에 시간을 너무 많이 잡아먹었네요..

 

하지만 구현이 빡센만큼 특별한 알고리즘은 없는거 같습니다.

 

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

public class Main {
	static Queue<Integer>[][] map = new LinkedList[4][4];
	static Queue<Integer>[][] copy = new LinkedList[4][4];
	static boolean[][] visited ;
	static int[][] visitCnt;
	static int[][] smellMap = new int[4][4];
	static int[] sharkDir = new int[3];
	static int M, S, max;
	static Shark shark;
	// ←, ↖, ↑, ↗, →, ↘, ↓, ↙ 물고기 이동 
	static int[] dx = {0, -1, -1, -1, 0, 1, 1, 1};
	static int[] dy = {-1, -1, 0, 1, 1, 1,  0, -1};
	// 상좌하우 상어 
	static int[] sx = {-1, 0, 1, 0};
	static int[] sy = {0, -1, 0, 1};
	
	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		M = Integer.parseInt(st.nextToken());
		S = Integer.parseInt(st.nextToken());
		
		for(int i = 0 ; i < 4 ; i++) {
			for(int j = 0 ; j < 4 ; j++) {
				map[i][j] = new LinkedList<Integer>();
				copy[i][j] = new LinkedList<Integer>();
			}
		}
		
		for(int i = 0 ; i < M ; i++) {
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken()) - 1;
			int y = Integer.parseInt(st.nextToken()) - 1;
			int d = Integer.parseInt(st.nextToken()) - 1;
			map[x][y].add(d);
			
		}
		st = new StringTokenizer(br.readLine());
		shark = new Shark(Integer.parseInt(st.nextToken()) - 1, Integer.parseInt(st.nextToken()) - 1);
		
		for(int i = 0 ; i < S ; i++) {
			//물고기 복사 
			copyFishmap();
			
			// 물고기 이동 
			moveFish();
			
			// 상어 이동
			moveShark();
			
			// 두번전 물고기 냄새 없애기 visited
			fishSmellDelete();
			
			//물고기 복사 떠놓은거 map 넣기 
			insertCopyFish();
		}
		max = 0;
		for(int i = 0 ; i < 4; i++) {
			for(int j = 0 ; j < 4 ; j++) {
				max += map[i][j].size();
			}
		}
		System.out.println(max);
	}
	
	private static void insertCopyFish() {
		for(int i = 0 ; i < 4;  i++) {
			for(int j = 0 ; j < 4; j++) {
				
				while(!copy[i][j].isEmpty()) {					
					map[i][j].add(copy[i][j].poll());
				}
			}
		}
	}

	private static void fishSmellDelete() {
		for(int i = 0 ; i < 4;  i++) {
			for(int j = 0 ; j < 4; j++) {
				if(smellMap[i][j] != 0) smellMap[i][j] -= 1;
			}
		}
	}

	private static void moveShark() {
		//상 좌 하 우 
		max = Integer.MIN_VALUE;
		visitCnt = new int[4][4];
		findSharkDir(0, 0, shark.x, shark.y, new int[]{-1, -1, -1});
		visited = new boolean[4][4];
		for(int i = 0 ; i < 3; i++) {
			shark.x = shark.x + sx[sharkDir[i]];
			shark.y = shark.y + sy[sharkDir[i]];
			if(map[shark.x][shark.y].size() != 0 && visited[shark.x][shark.y] == false) {
				visited[shark.x][shark.y] = true;
				
				map[shark.x][shark.y].clear();
				
				smellMap[shark.x][shark.y] = 3;
			}
		}
		
	}
	private static void findSharkDir(int depth, int count, int x, int y, int[] arr) {
		if(depth == 3) {
			if(count > max) {
				for(int i = 0 ; i < 3; i++) {
					sharkDir[i] = arr[i];
					max = count;
				}
			}
			return;
		}
		for(int dir = 0 ; dir < 4; dir++) {
			int nx = x + sx[dir];
			int ny = y + sy[dir];
			
			if(0 > nx || nx >= 4 || 0 > ny || ny >= 4) continue;
			arr[depth] = dir;
			if(visitCnt[nx][ny] == 0) {
				visitCnt[nx][ny] += 1;
				findSharkDir(depth + 1, count + map[nx][ny].size(), nx, ny, arr);
			}
			else {
				visitCnt[nx][ny] += 1;
				findSharkDir(depth + 1, count, nx, ny, arr);
			}
			visitCnt[nx][ny] -= 1;
		}
	}

	private static void moveFish() {
		int[][] sizeMap = new int[4][4];
		for(int x = 0 ; x < 4 ; x++) {
			for(int y = 0 ; y < 4; y++) {
				sizeMap[x][y] = map[x][y].size();
			}	
		}
		
		for(int x = 0 ; x < 4 ; x++) {
			for(int y = 0 ; y < 4; y++) {
				int size = sizeMap[x][y];
				if(size == 0) continue;
				
				Loop : for(int idx = 0 ; idx < size ; idx++) {
					int dir = map[x][y].poll();
					
					for(int d = 0 ; d < 8 ; d++) {
						
						if(d != 0) dir -= 1;
						if(dir == -1) dir = 7;
						int nx = x + dx[dir];
						int ny = y + dy[dir];
						
						if(0 > nx || nx >= 4 || 0 > ny || ny >= 4) continue;
						
						if(nx == shark.x && ny == shark.y) continue;
						
						if(smellMap[nx][ny] != 0) continue;
						
						map[nx][ny].add(dir);
						continue Loop;
					}
					// 다돌고 없으면 갈 수 있는곳이 없으면 제자리
					dir -= 1;
					map[x][y].add(dir);
				}
			}
		}
	}
	private static void copyFishmap() {
		for(int i = 0 ; i < 4 ; i++) {
			for(int j = 0 ; j < 4 ; j++) {
				copy[i][j].clear();
				int size = map[i][j].size();
				
				if(size > 0) {
					for(int k = 0 ; k < size ; k ++) {
						int tmp = map[i][j].poll();

						copy[i][j].add(tmp);
						map[i][j].add(tmp);
					}
				}
			}
		}
	}

	private static class Shark{
		int x, y;

		public Shark(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}
반응형
저작자표시 (새창열림)

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

[Java/자바 백준 1459] 걷기  (0) 2022.03.29
[Java/자바 백준 1781] 컵라면  (0) 2022.03.29
[Java/자바 백준 16928] 뱀과 사다리 게임  (0) 2022.03.27
[Java/자바 백준 16954] 움직이는 미로 탈출  (0) 2022.03.11
[Java/자바 백준 1976] 여행가자  (0) 2022.03.09
    '알고리즘/문제 풀이' 카테고리의 다른 글
    • [Java/자바 백준 1459] 걷기
    • [Java/자바 백준 1781] 컵라면
    • [Java/자바 백준 16928] 뱀과 사다리 게임
    • [Java/자바 백준 16954] 움직이는 미로 탈출
    광규니
    광규니
    공부 및 일상 올리기~

    티스토리툴바