일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- django windows 배포 에러
- django 웹 페이지
- The requested operation has failed!
- windows apache wsgi 에러
- 18233 java
- 18233 비트마스킹
- 14711 java
- 2961 java
- django settings.py
- 1188 음식 평론가
- 14711 타일 뒤집기
- APPEND_SLASH = FALSE
- 공유기 원격 설정
- 1188 java
- 원격 연결 포트 포워딩
- django 프로젝트 시작
- 2661 좋은 수열
- django apache deploy error
- Problems occurred while performing provisioning operation
- 18233 러버덕
- java di
- apache pythonpath
- 2661 java
- django httpd error
- django The requested operation has failed!
- windows 원격 연결 설정
- 2961 도영이가 만든 맛있는 음식
- 2643 색종이 올려 놓기
- django
- 2643 java
라이브러리는 도서관 아닌가요
백준 (BOJ) 16236 아기 상어 java 본문
* 풀이가 아니니 문제 풀이하시는 데에 참고하지 않길 당부드립니다.
풀다가 테스트케이스에서 여러 번 막힌 덕분에 약간의 분노를 느껴 복습을 위해 남기는 포스트이다.
항상 구현/시뮬레이션 문제 풀면 조건 확실히 숙지하고 가자.
아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고,
나머지 칸은 모두 지나갈 수 있다.
따라서, 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다.
아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다.
아기 상어는 자신의 크기와 같은 수(2렙이면 2마리, 3렙이면 3마리)의 물고기를 먹을 때 마다 크기가 1 증가한다.
테케 3번 진행 이미지)
위의 이미지는 잘못되었다. 처음 1을 섭취한 후 3을 지나 저렇게 갈 수 없다.
해당 시점에 아기 상어의 크기는 2이기 때문이다. 자신 보다 큰 3을 지날 수 없다.
처음 조건을 잘못 이해해서 저기서 꽤 고생했다. 반면교사하자.
1. q만 쓰면 될 것 같았는데 결국 pq도 썼다.
먼저 q로 탐색 범위를 훑고,
다음 pq는 해당 phase에서 먹을 수 있는 물고기들이 나왔을 때 다음의 우선 순위
① 최단 거리
② 보다 높은 위치
③ 보다 왼쪽 위치
를 만족시켜서, 먹을 수 있는 물고기의 위치를 넣으면 알아서 정렬시켜준다.
그리고 조건을 만족시키는 도착 지점의 위치를 함수의 끝에서 뱉어준다(poll).
물론 다 q로 다 훑었는데도 찾지 못했다면, boolean check가 false로 나타나 끝에서 잘못된 place를 뱉는다.
(이 부분은 bfs 메서드의 return 타입을 boolean으로 맞춰서 더 최적화할 수 있을 거 같다.)
잘못된 place를 받은 main에서 판단하여, 엄마 상어를 부를 것인지를 정한다. (boolean flag가 체크 후 루프 종료)
그리고 q, pq와 visited는 매번 시작지점으로부터 진행될 때마다 bfs에서 새로 할당된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
// ***** 아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고,
// 나머지 칸은 모두 지나갈 수 있다.
// 아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다.
// 따라서, 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다.
// ** 아기 상어는 자신의 크기와 같은 수(2렙이면 2마리, 3렙이면 3마리)의 물고기를 먹을 때 마다 크기가 1 증가한다.
class place implements Comparable<place>{
int x, y, count;
place(int x, int y, int count){
this.x = x;
this.y = y;
this.count = count;
}
@Override
public int compareTo(place p){
// 우선 순위 1: 이동 거리
if(this.count > p.count){ // 새로 들어오는 p가 짧다면, 1 return
return 1;
}else{
// 우선 순위 2: 높이
if(this.y > p.y) return 1; // 앞에 위치
else if(this.y == p.y){ // 높이가 같다면, 우선 순위 3: 왼쪽
if(this.x > p.x) return 1;
else return -1;
}
else return -1; // 뒤에 위치
}
}
}
public class Main {
static int[][] map;
static int N;
static int[] dx = {0,-1,0,1};
static int[] dy = {-1,0,1,0};
static boolean[][] visited;
static int level; // 현재 아기 상어의 크기(level)
static int needed; // 다음 레벨로 가기 위해 요구되는 상어 수
static PriorityQueue<place> pq; // 해당 phase 에서 "최단 거리, 더 높은, 왼쪽"을 기준으로 정렬된 pq
static Queue<place> q;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
map = new int[N][N];
int x = 0, y = 0; // the current place of a baby shark.
StringTokenizer st;
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());
if(map[i][j] == 9){
y = i;
x = j;
map[i][j] = 0;
}
}
}
boolean flag = true;
int count = 0; // 총 움직인 시간, 초기 값 == 0
level = 2; // 시작 크기
needed = level; // 필요한 먹이 수(시작은 level 동일)
// System.out.println("시작 위치= " + x + " " + y);
while (flag){
place p = bfs(x, y, count);
if(p.x == -1 && p.y == -1){
flag = false;
}else{
x = p.x;
y = p.y;
count = p.count;
//*** '먹음' 처리: return 될 때 실제 방문하는 place 를 받을 수 있다.
map[y][x] = 0;
// System.out.println("위치= " + x + " " + y + ", 이동거리= " + count + ", level= " + level);
}
}
System.out.print(count);
}
public static place bfs(int x, int y, int count){
// 새로 선언해줘야 할 3가지 것들.
visited = new boolean[N][N];
q = new LinkedList<>();
pq = new PriorityQueue<>();
q.add(new place(x, y, count));
visited[y][x] = true;
boolean check = false; // 먹을 거 있나 체크
while (!q.isEmpty()){
place p = q.poll();
int px = p.x;
int py = p.y;
int pCount = p.count+1; // 미리 한 칸 이동할 거 생각해서 더해놓기
for(int i=0; i<4; ++i){
int nx = px + dx[i];
int ny = py + dy[i];
if(nx >= 0 && nx < N && ny >= 0 && ny < N){
if(!visited[ny][nx] && map[ny][nx] <= level){
// 지나갈 수 있는 곳이므로, 일단 방문체크
visited[ny][nx] = true;
// 빈 공간이 아니고, 현재 아기상어 레벨 보다 낮으면 '먹음'
if(map[ny][nx] < level && 0 < map[ny][nx]){
check = true; //** '먹을 것 있나' 체크
// 일단 후보군 중 하나는 넣고보자.
pq.add(new place(nx, ny, pCount));
}else{ // 먹이가 아닌 곳을 지난다면,
if(!check) {
q.add(new place(nx, ny, pCount));
}
}
}
}
}
}
if(check){
// 먹을 것 찾았으니까, 요구되는 '먹이' 감소
--needed;
// 필요한 만큼 먹어치웠다면: level up, needed 갱신
if(needed == 0){
++level;
needed = level;
}// else 생략: 먹긴 먹었는데 아직 덜 먹었다면, pass
return pq.poll();
}
else{
return new place(-1, -1, -1);
}
}
}
'알고리즘 문제' 카테고리의 다른 글
백준 (BOJ) 15810 풍선 공장 java (0) | 2022.04.05 |
---|---|
백준 (BOJ) 10815 숫자 카드 java (0) | 2022.03.25 |
백준(BOJ) 2133 타일 채우기 java (0) | 2022.03.21 |
백준(BOJ) 1025 제곱수 찾기 java (0) | 2022.03.18 |
백준(BOJ) 1991 트리 순회 java (0) | 2022.03.15 |