티스토리 뷰
1. 문제
https://www.acmicpc.net/problem/19236
19236번: 청소년 상어
첫째 줄부터 4개의 줄에 각 칸의 들어있는 물고기의 정보가 1번 행부터 순서대로 주어진다. 물고기의 정보는 두 정수 ai, bi로 이루어져 있고, ai는 물고기의 번호, bi는 방향을 의미한다. 방향 bi는
www.acmicpc.net
2. 풀이
- 상어의 위치를 DFS를 이용해 움직인다.
- 상어와 물고기를 각각 객체를 만들어 사용한다.
- 물고기(Fish)는 좌표, 물고기 번호, 방향, 살아있는지 여부를 멤버 변수로 갖는다.
- 상어(Shark)는 좌표, 방향, 먹은 물고기 번호의 합을 멤버 변수로 갖는다.
- 물고기 번호를 입력 받고, 탐색을 시작하기전,
- 물고기를 번호 순서대로 먹기 위해 물고기가 담긴 list를 번호순으로 오름차순 정렬한다
- 상어가 (0,0)로 이동해 (0,0)에 있는 물고기를 먹는다.
- DFS로 물고기를 이동하는데 먼저 모든 살아있는 물고기들을 이동한다(moveFish())
- 반시계방향으로 이동하기 위해 이동 좌표를 담은 배열 dir에 반시계방향으로 값을 넣는다.
- 상어가 해당 방향으로 1칸 이상 이동할 수 있기 때문에 for문을 이용해 최대 3배수까지 움직인다.
- 먹히거나 상어가 있는 자리는 지나지 않는다.
- map[i][j] == 0 : 먹힌 자리
- map[i][j] == -1: 상어가 있는 자리
- 먹을 수 있는 물고기를 먹고, 계속해서 DFS를 진행해 먹을 수 있는 물고기 번호 합의 최댓값을 구한다
3. 코드
import java.util.*;
import java.io.*;
class Main{
// 청소년 상어
static class Fish { // 물고기
int x, y, number, dir;
boolean isAlive; // 상어에게 먹히지 않고 살아있는지
public Fish(int x, int y, int number, int dir, boolean isAlive) {
this.x = x;
this.y = y;
this.number = number;
this.dir = dir;
this.isAlive = isAlive;
}
public Fish() {}
}
static class Shark{ // 상어
int x, y, dir, sum; // 좌표, 방향, 먹은 물고기 번호 합
public Shark(int x, int y, int dir, int sum) {
this.x = x;
this.y = y;
this.dir = dir;
this.sum = sum;
}
}
// 반시계방향
static int[][] dir = {{-1,0},{-1,-1},{0,-1},{1,-1},
{1,0},{1,1},{0,1},{-1,1}};
static int max = 0;
// 주어진 좌표가 map 범위 내인지
public static boolean isInRange(int x, int y) {
return (x >= 0 && x < 4 && y >= 0 && y < 4);
}
public static int[][] copyMap(int[][] map) {
int[][] tmp = new int[4][4];
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
tmp[i][j] = map[i][j];
return tmp;
}
public static ArrayList<Fish> copyList(ArrayList<Fish> fishes){
ArrayList<Fish> tmp = new ArrayList<Fish>();
fishes.forEach(e -> tmp.add(new Fish(e.x, e.y, e.number, e.dir, e.isAlive)));
return tmp;
}
// 빈 칸 또는 다른 물고기 있는 칸으로 물고기 이동
public static void moveFish(Fish f, int[][] map, ArrayList<Fish> fishes) {
if(f.isAlive == false) return;
for(int i = 0; i < 8; i++) {
int nDir = (f.dir + i) % 8;
int nX = f.x + dir[nDir][0];
int nY = f.y + dir[nDir][1];
// 상어 있는 자리는 지나지 않음
if(!isInRange(nX, nY) || map[nX][nY] == -1) continue;
map[f.x][f.y] = 0;
if(map[nX][nY] == 0) { // 빈 자리면 바로 이동
f.x = nX;
f.y = nY;
}else { // 빈자리 아니면 다른 물고기와 변경
Fish tmp = fishes.get(map[nX][nY] - 1);
tmp.x = f.x;
tmp.y = f.y;
map[f.x][f.y]= tmp.number;
f.x = nX;
f.y = nY;
}
map[nX][nY] = f.number;
f.dir = nDir;
return;
}
}
// dfs를 통해 상어 이동
public static void dfs(int[][] map, ArrayList<Fish> fishes, Shark shark) {
if(max < shark.sum) {
max = shark.sum;
}
// 모든 살아있는 물고기 이동
fishes.forEach(e -> moveFish(e, map, fishes));
// 4*4이므로 최대 3배수까지 움직일 수 있음
for(int i = 1; i < 4; i++) {
int nX = shark.x + dir[shark.dir][0] * i;
int nY = shark.y + dir[shark.dir][1] * i;
// 먹히거나 상어 있는 자리는 지나지 않음
if(!isInRange(nX, nY) || map[nX][nY] <= 0) continue;
// 물고기 잡아먹고 dfs 계속
int[][] cMap = copyMap(map);
ArrayList<Fish> cFishes = copyList(fishes);
Fish eatenFish = cFishes.get(map[nX][nY] - 1); // 물고기 잡아 먹음
cMap[shark.x][shark.y] = 0;
eatenFish.isAlive = false;
cMap[eatenFish.x][eatenFish.y] = -1; // 새로운 상어 위치
Shark nShark = new Shark(eatenFish.x, eatenFish.y, eatenFish.dir, shark.sum + eatenFish.number);
dfs(cMap, cFishes, nShark);
}
}
public static void main (String[] args) throws java.lang.Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int[][] map = new int[4][4];
ArrayList<Fish> fishes = new ArrayList<>();
for(int i = 0; i < 4; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for(int j = 0; j < 4; j++) {
Fish f = new Fish();
f.number = Integer.parseInt(st.nextToken());
f.dir = Integer.parseInt(st.nextToken()) - 1;
f.x = i;
f.y = j;
f.isAlive = true;
map[i][j] = f.number;
fishes.add(f);
}
}
// 물고기를 번호순으로 오름차순 정렬
Collections.sort(fishes, new Comparator<Fish>() {
@Override
public int compare(Fish f1, Fish f2) {
return f1.number - f2.number;
}
});
// 상어가 (0,0) 위치의 물고기를 먹음
Fish f = fishes.get(map[0][0] - 1);
f.isAlive = false;
map[f.x][f.y] = -1; // 상어 위치
Shark shark = new Shark(0, 0, f.dir, f.number);
dfs(map, fishes, shark);
System.out.println(max);
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[JAVA/DP] 백준 12865 평범한 배낭 (0) | 2021.11.24 |
---|---|
[JAVA/우선순위큐] 백준 1715 카드 정렬하기 (0) | 2021.10.29 |
[JAVA/구현] 백준 14500 테트로미노 (0) | 2021.10.23 |
[JAVA/BFS,구현] 백준 13460 구슬 탈출 2 (0) | 2021.10.22 |
[JAVA/백트래킹] 백준 14889 스타트와 링크 (0) | 2021.10.22 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- mysql
- 스티커모으기2
- java
- hc-06
- 구슬 탈출2
- dht11
- 아두이노
- the pads
- ESP8266
- 리눅스
- BFS
- 워드프레스
- 메일서버
- 백준
- 라즈비안
- 2981
- 합승 택시 요금
- git
- 11503
- 집배원 한상덕
- DP
- 블루투스
- dovecot
- FTP
- 라즈베리파이
- hackerrank
- 키 순서
- 자바
- 프로그래머스
- c++
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함