티스토리 뷰
https://www.acmicpc.net/problem/1486
1486번: 등산
첫째 줄에 산의 세로크기 N과 가로크기 M 그리고, T와 D가 주어진다. N과 M은 25보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 지도가 주어진다. T는 52보다 작거나 같은 자연수이고, D는 1,000
www.acmicpc.net

문제
세준이는 등산광이다. 세준이는 높은 곳에서 도시를 내려다 보는 것을 좋아한다. 하지만, 겁이 많은 세준이는 어두워지기 전에 호텔로 내려오려고 한다.
세준이가 가려고하는 산의 지도가 입력으로 주어진다. 산의 지도를 M이라고 했을 때, M[i][j]는 (i,j)의 높이가 M[i][j]라는 것을 의미한다. 그 값이 'A'-'Z'일 때는 0-25를 뜻하는 것이고, 'a'-'z'일 때는, 26-51을 뜻한다.
세준이의 호텔은 (0,0)에 있다. 그리고, 세준이는 지금 위치에서 바로 인접한 정수 좌표 중 높이의 차이가 T보다 크지 않은 곳으로만 다닐 수 있다.
만약 세준이가 현재 위치에서 높이가 낮은 곳이나 같은 곳으로 이동한다면 시간은 1초가 걸린다. 하지만 높은 곳으로 이동한다면 두 위치의 높이의 차이의 제곱만큼 시간이 걸린다. 예를 들어 높이가 5에서 높이가 9인 곳으로 간다면, 시간은 (5-9)2=16초가 걸린다. 하지만, 높이가 9인 곳에서 5인 곳으로 간다면 시간은 1초가 걸린다.
산의 지도와, T, 그리고 어두워지는 시간 D가 주어졌을 때, 세준이가 D보다 크지 않은 시간 동안 올라갈 수 있는 최대 높이를 구하는 프로그램을 작성하시오.(세준이는 호텔에서 출발해서 호텔로 돌아와야 한다.)
유형 : 다익스트라
접근 방식
- 세준이는 호텔에서 출발해서 다시 호텔로 돌아와야 한다.
- 이 문제는 다익스트라를 2번 사용해서 풀 수 있다.
- 처음에는 (0,0) -> (n,m)으로 올라가는 과정
- 두 번째는 (n,m) -> (0,0)으로 과는 과정
- 구현 방법은 간단하다. 간선의 정보를 반대로 하면 된다. 처음에 올라가는 간선을 두번째 탐색때는 반대로 설정하면 된다.
- 즉 높이 차이가 높은곳에 낮은 곳으로 가는 것을 처음 탐색때는 1로 설정하지만 두번째 탐색때는 제곱 차이값으로 해야 한다.
주의할점이 높이가 같은 곳간의 이동은 첫번째 탐색이나 두번째 탐색 모두 1이다. -> 이것 때문에 10번을 박았다 ㅜㅡㅜ
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static int n = 0;
static int m = 0;
static int k = 0;
static int d = 0;
static int[][] board;
static int[][] tmpDis;
static int[] dx = {0,0,-1,1};
static int[] dy = {1,-1,0,0};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine()," ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
k = Integer.parseInt(st.nextToken());
d = Integer.parseInt(st.nextToken());
board = new int[n + 1][m + 1];
tmpDis = new int[n+1][m+1];
for(int i = 0 ; i < n ; i++){
char[] arr = br.readLine().toCharArray();
for(int j = 0 ; j < m ; j++){
if(arr[j] >= 'A' && arr[j] <= 'Z'){
board[i][j] = arr[j] - 'A';
}
else{
board[i][j] = arr[j] - 'a' + 26;
}
}
}
bfs();
bfs2();
int result = board[0][0];
for(int i = 0 ; i < n ; i++){
for(int j = 0; j < m ; j++){
if(tmpDis[i][j] <= d){
result = Math.max(result,board[i][j]);
}
}
}
System.out.println(result);
br.close();
}
static void bfs(){
int result = 0;
Queue<int[]> q = new ArrayDeque<>();
int[][] dis = new int[n][m];
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
dis[i][j] = d + 1;
}
}
dis[0][0] = 0;
q.add(new int[]{0,0,0});
while(!q.isEmpty()){
int[] cur = q.poll();
if(dis[cur[0]][cur[1]] < cur[2])
continue;
dis[cur[0]][cur[1]] = cur[2];
for(int i = 0 ; i < 4 ; i++){
int nx = cur[0] + dx[i];
int ny = cur[1] + dy[i];
if(nx < 0 || nx >= n || ny < 0 || ny >= m)
continue;
if(Math.abs(board[nx][ny] - board[cur[0]][cur[1]]) > k)
continue;
if(board[nx][ny] > board[cur[0]][cur[1]]){
int tmpDis = Math.abs(board[nx][ny] - board[cur[0]][cur[1]]);
tmpDis = tmpDis * tmpDis;
int next = dis[cur[0]][cur[1]] + tmpDis;
if(next > d)
continue;
if(dis[nx][ny] > next){
dis[nx][ny] = next;
q.add(new int[]{nx,ny,dis[nx][ny]});
}
}else{
if(dis[cur[0]][cur[1]] + 1 > d)
continue;
if(dis[nx][ny] > dis[cur[0]][cur[1]] + 1) {
dis[nx][ny] = dis[cur[0]][cur[1]] + 1;
q.add(new int[]{nx,ny,dis[nx][ny]});
}
}
}
}
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
tmpDis[i][j] += dis[i][j];
}
}
}
static void bfs2(){
int result = 0;
Queue<int[]> q = new ArrayDeque<>();
int[][] dis = new int[n][m];
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
dis[i][j] = d + 1;
}
}
dis[0][0] = 0;
q.add(new int[]{0,0,0});
while(!q.isEmpty()){
int[] cur = q.poll();
if(dis[cur[0]][cur[1]] < cur[2])
continue;
dis[cur[0]][cur[1]] = cur[2];
for(int i = 0 ; i < 4 ; i++){
int nx = cur[0] + dx[i];
int ny = cur[1] + dy[i];
if(nx < 0 || nx >= n || ny < 0 || ny >= m)
continue;
if(Math.abs(board[nx][ny] - board[cur[0]][cur[1]]) > k)
continue;
if(board[nx][ny] < board[cur[0]][cur[1]]){
int tmpDis = Math.abs(board[nx][ny] - board[cur[0]][cur[1]]);
tmpDis = tmpDis * tmpDis;
int next = dis[cur[0]][cur[1]] + tmpDis;
if(next > d)
continue;
if(dis[nx][ny] > next){
dis[nx][ny] = next;
q.add(new int[]{nx,ny,dis[nx][ny]});
}
}else{
if(dis[cur[0]][cur[1]] + 1 > d)
continue;
if(dis[nx][ny] > dis[cur[0]][cur[1]] + 1) {
dis[nx][ny] = dis[cur[0]][cur[1]] + 1;
q.add(new int[]{nx,ny,dis[nx][ny]});
}
}
}
}
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
tmpDis[i][j] += dis[i][j];
}
}
}
}'알고리즘 > 백준' 카테고리의 다른 글
| 백준 12763 (지각하면 안 돼) - java (0) | 2024.03.27 |
|---|---|
| 백준 22868 산책 (small) (0) | 2024.03.25 |
| 백준 17281 (⚾) - ja (0) | 2024.02.27 |
| 백준 2001 (보석 줍기) - java (0) | 2024.02.26 |
| 백준 20005 (보스몬스터 전리품) - java (2) | 2024.02.20 |
- Total
- Today
- Yesterday
- 백준 #인구 이동 #16234
- 백준 #12014 #주식 #자바 #java
- 백준 #15686 #치킨 배달
- 백준 #14863 #서울에서 경산까지 #java #자바
- 자바 #JAVA
- 백준 #13549 #숨바꼭질3
- Java
- 백준 #
- 백준 #다리 만들기 #2146
- 백준 #2580 #스도쿠
- 백준 #1987 #알파벳 #자바 #java
- 행복합시다.
- 백준 #치즈 #2638
- 자바
- 백준 #2636 #치즈
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
- 17394
- 백준 #1325 #효율적인 해킹
- 17218
- 백준 #3980 #선발 명단
- 백준 #18405 #경쟁적 전염
- 백준 #4963 #섬의 개수
- 백준 #1759 #암호 만들기
- 올해보다
- 백준 #1584 #게임 #java #자바
- 백준 #25603 #짱해커 이동식 #java #자바
- 백준 #5721 #사탕 줍기 대회 #java #자바
- 백준
- 백준 #17940 #주식 #자바 #java
- 백준 #16973 #직사각형 탈출
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |