[JAVA] 알고스팟 외발뛰기 - JUMPGAME 문제 해설.
프로그래밍 대회에서 배우는 알고리즘 문제해결전략 (속칭 종만북) 8단원의 동적 계획법(Dynamic Programming) 첫문제
알고스팟에서는 ID: JumpGame으로 찾으면 나오는 문제이다.
https://algospot.com/judge/problem/read/JUMPGAME
<해결방법 및 해설>
해설이라고 적어놓긴 했지만, 완벽히 주관적인 입장에서 적었으니 맹신하지는 않았으면 좋겠다. 틀린부분도 엄청많을 수도 있고.
일단, 이문제는 완전탐색으로 하면 틀리는 문제다. 3000ms이기때문에, 시간이 부족해서 중복되는 결과를 바로바로 처낼수 있어야한다.
그것이 완전탐색과 이 동적계획법이 가지는 큰 차이점이겠다. 그럼 그걸 어떻게 할거냐?
중복값이 나오면 무조건 그값을 리턴하고 그 후 무시하고 진행하는 것으로 실행시키면된다.
처음에 나는 이 함수폼이 int값을 return하는 것이 이해가 잘 안갔는데, 이 중복값을 return시키기 위해서 꼭 int 값을 해야한다.
boolean으로 하면 완전탐색꼴이되서 시간초과가 날것임.
그리고 답을 출력할때
0을 리턴하는 경우 1을 리턴하는 경우를 명확하게 판단해서 조건문 쓸때 잘써야됨. ㅋㅋ 괜히 값이 역으로 나올 수도 있고, 다 맞춰놓고 답이 틀리는 경우가 있다.
7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 0
테스트 케이스중에서 자신의 코드가 잘 돌아가는지 확인해보기 쉬운 꼴중 하나이다.
무조건 NO가 나와야되고, 저기서 2부분을 1로 바꾸면 무조건 YES가 나와야한다.
import java.util.*;
public class JumpGame {
static int n;
static int board [][] = new int[100][100];
static int cache[][] = new int[100][100];
static int ret = 0;
static int jump(int y, int x){
if(y>=n || x>= n){
return 0; //이건 x나 y가 보 범위 벗어나면 0을 출력~
}
if(y ==n-1 && x==n-1){
return 1;// 끝지점에 도착하는게 이거임. 1
}
if(cache[y][x] != -1){
return cache[y][x];
}
int jumpSize = board[y][x];
return cache[y][x] = jump(y+jumpSize, x) | jump(y, x+jumpSize);
}
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
int tc = input.nextInt();
while(tc>0){
n = input.nextInt();
//해맨부분 -> 전역변수를 활용하지 못했다. int N이라고 써놓고 삽질함. 즉, 이소리는 jump함수안에는 n크기를 판단해서 돌아가는데, 이건 모른다는것.
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
board[i][j] =input.nextInt();
cache[i][j] = -1;
//해맨 부분은 cache 초기화 안해줘서 000으로 초기화 되있어서 0나올리는 없겠지만,만약나왔다면 오류나서 문제 아마틀렸을거임.
}
}
if(jump(0,0)==1){ // 함수작동시키는 법은 대충 이럼 (0,0)처럼 시작지점에 스타트만 시켜주면 자기가 알아서 굴러가는 거지
System.out.println("YES");
}
if(jump(0,0)!=1){
System.out.println("NO");
}
// 이거말고도 4줄을 단 한줄에 적어버리는 방법이 있더라~)
// //System.out.println (jump(0,0) !=0 ? "YES" : "NO");
//
// tc--;
}
}
}
?????
<사견 & 후기>
근데 그 책을 보면서 해도 조금의 문제점이 있기 마련이다.
책의 주력언어는 C++로 알고 있는데, 나는 Java로 하기 때문에 그 차이가 명확하게 튀어나온다.
예를들면, int& ret =cache[][]; 이런 구문이 있는데 처음에는 나는 이게 뭔지 몰랐다. (뭐라는 거야 쉬밤... 이러고 있었음)
근데 앞뒤 설명을 대략적으로 유추를 해서 그리고 책에서도 말하는 참조형이라는 데 유의하세요!
int& ret은 전역변수를 말하는 것이라는 걸 알아감,
즉, 자바에서는 static int ret으로 써야지 굴러가는 구문인것.
전역변수를 설정하는 다른 방법이 있겠으나, 아직 내 지식으로는 전역변수를 설정하는게 static int 가 가장 안전하다고 판단했다.
주석에 내가 해맨 부분들이 있다. 아마 그런 부분에서 실수하기 쉬운 문제 인것 같다.
그리고 논리적으로는 어떤식으로 굴러가는지 알기 쉬운 데 반면 코드를 실행시키고 내가 원한 값이 안나오는 대표적인 재귀함수꼴문제라서 디버깅하기도 쉽지 않더라..
아직 코드 뉴비라서 재귀함수 문제는 디버깅을 어떤식으로 해야지 잘 모르겠다.
참조: 도움을 많이 받은 사이트들 같이 보면 좋다!..
http://redscreen.tistory.com/169
https://github.com/congr/world/blob/master/algospot/JumpGame.java
http://gwpark.tistory.com/1812