Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- BFS
- 취득후기
- 다익스트라
- 백준코딩테스트
- 완전탐색
- 다이나믹프로그래밍
- COSPROJAVA1급
- 이젠 골드구현도 어렵네..
- 시뮬레이션
- spring
- 백준
- 게더타운시작
- GatherTown
- java
- 재귀함수
- QUICKSTARTGUIDE
- 네트워크플로우
- PS
- DFS
- deque
- COSPRO
- 자바PS
- 세그먼트트리
- 01BFS
- 알고리즘
- dp
- 우선순위큐
- 엘라스틱서치
- 구현
- YBMCOS
Archives
- Today
- Total
공부공간
BOJ - 16930 ) 달리기 본문
https://www.acmicpc.net/problem/16930
NXM맵에서 직선방향으로 K만큼 이동할때에, 목적지까지 갈수있는 최단 시간을 구하는문제이다.
최단시간이고 N,M이 1000이라 BFS로 풀릴것같았다.
먼저, K만큼
1 ) 이동중 범위를 벗어나는경우
2 ) # 벽을 만나는경우
이 두가지의 경우에는 K를 break처리해주었다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
int sx=0,sy=0,ex=0,ey=0;
char map[][] = new char[n+1][m+1];
int visit[][] =new int[n+1][m+1];
for(int i = 1 ; i <= n ; i++) {
String str = br.readLine();
for(int j = 1; j<= m ; j++) {
map[i][j] = str.charAt(j-1);
visit[i][j] = 987654321;
}
}
st = new StringTokenizer(br.readLine());
sy = Integer.parseInt(st.nextToken());
sx = Integer.parseInt(st.nextToken());
ey = Integer.parseInt(st.nextToken());
ex = Integer.parseInt(st.nextToken()); //end input
int dir[][] = {{1,0},{-1,0},{0,1},{0,-1}};
ArrayDeque<int []> dq = new ArrayDeque<>();
dq.add(new int[] {sy,sx,1});
visit[sy][sx] =0;
while(!dq.isEmpty()) {
int now[] =dq.poll();
int nowy = now[0];
int nowx = now[1];
int time = now[2];
if(nowy == ey && nowx == ex) {
break;
}
for(int i = 0 ; i < 4 ; i++) {
// 한방향을 정해서,
for(int j = 1 ; j <=k ;j++) {
int ny = nowy + dir[i][0]*j;
int nx = nowx + dir[i][1]*j; // 갈수있는 최대 k까지
if(ny > 0 &&nx >0 && nx <= m &&ny <=n) {
if(map[ny][nx]=='.') {
if(visit[ny][nx] > time) {
// .이고 더 작은 시간으로 갈수있을때만 이동
visit[ny][nx] = time;
dq.add(new int[] {ny,nx,time+1});
}
} else {
break;// 벽에 막힌경우
}
}
}
}
}System.out.println(visit[ey][ex] = visit[ey][ex] == 987654321 ? -1 : visit[ey][ex]);
}
}
또 다른경우가 존재한다.. ( 한참고민 )
한 시간 내에 k만큼 이동할때에 Queue에는 1-k까지의 좌표들이 들어있게되는데, 사실상 모두 같은 시간을 가짐에도,
Queue에서 나왔을때에 같은 방향으로 k만큼 또 계산하게된다..
. . . .
. . . .
. . . .
. . . .
이러한 맵에서 시간1초후 Visit 배열은
1 1 1 1
1 . . .
1 . . .
1 . . .
가 될텐데, (1,2)의 노드에서 다시 하나를뽑아도 (1,3) (1,4) 쪽으로 for문이 돌게된다.
즉, 방문하지않았고, 방문했다면 더 적은시간이 체크된쪽을 방문할때에는 멈추어 주어야한다.
위와같은상황에서 (1,3) , (1,4)쪽으로 진행되는 방향은 다시볼 필요가 없기 때문이다.
즉 visit[ny][nx] <= visit[nowy][nowx] 처럼 내가 가려고하는쪽이 같거나 더작은 시간을 가지고있다면,
볼필요가 없게되는 것이다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
int sx=0,sy=0,ex=0,ey=0;
char map[][] = new char[n+1][m+1];
int visit[][] =new int[n+1][m+1];
for(int i = 1 ; i <= n ; i++) {
String str = br.readLine();
for(int j = 1; j<= m ; j++) {
map[i][j] = str.charAt(j-1);
}
}
st = new StringTokenizer(br.readLine());
sy = Integer.parseInt(st.nextToken());
sx = Integer.parseInt(st.nextToken());
ey = Integer.parseInt(st.nextToken());
ex = Integer.parseInt(st.nextToken()); //end input
int dir[][] = {{1,0},{-1,0},{0,1},{0,-1}};
ArrayDeque<int []> dq = new ArrayDeque<>();
dq.add(new int[] {sy,sx});
visit[sy][sx] =0;
top :
while(!dq.isEmpty()) {
int now[] =dq.poll();
int nowy = now[0];
int nowx = now[1];
for(int i = 0 ; i < 4 ; i++) {
// 한방향을 정해서,
for(int j = 1 ; j <=k ;j++) {
int ny = nowy + dir[i][0]*j;
int nx = nowx + dir[i][1]*j; // 갈수있는 최대 k까지
if(ny > 0 &&nx >0 && nx <= m &&ny <=n && map[ny][nx]=='.') {
if(visit[ny][nx]==0) {
// .이고 더 작은 시간으로 갈수있을때만 이동
visit[ny][nx] = visit[nowy][nowx]+1;
if(ny == ey && nx == ex) {break top;}
dq.add(new int[] {ny,nx});
} else if(visit[ny][nx] <= visit[nowy][nowx]) {
// 더작은시간이 이미 계산되어있는 곳이라면 stop
break;
}
} else {
break;
}
}
}
}System.out.println(visit[ey][ex] = visit[ey][ex] == 0 ? -1 : visit[ey][ex]);
}
}
'알고리즘 > 완전탐색(BFS,DFS)' 카테고리의 다른 글
BOJ - 2665 ) 미로만들기 (0) | 2020.08.31 |
---|---|
BOJ - 19238 ) 스타트 택시 (0) | 2020.08.02 |
BOJ - 19236 ) 청소년상어 (0) | 2020.06.13 |
BOJ -16929 ) Two Dots (1) | 2020.06.02 |
BOJ - 18809 ) Gaaaaaaaaaarden (1) | 2020.05.28 |
Comments