본문 바로가기

알고리즘 문제

[C/C++ 백준 1890번] 점프 (Silver 2)

https://www.acmicpc.net/problem/1890

 

1890번: 점프

문제 N×N 게임판에 수가 적혀져 있다. 이 게임의 목표는 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 점프를 해서 가는 것이다. 각 칸에 적혀있는 수는 현재 칸에서 갈 수 있는 거리를 의미한다. 반드시 오른쪽이나 아래쪽으로만 이동해야 한다. 0은 더 이상 진행을 막는 종착점이며, 항상 현재 칸에 적혀있는 수만큼 오른쪽이나 아래로 가야 한다. 한 번 점프를 할 때, 방향을 바꾸면 안 된다. 즉, 한 칸에서 오른쪽으로 점프를 하거나, 아래로

www.acmicpc.net

코드업 1099번이 생각나는 문제이다. 해당 문제도 재귀함수로 풀었었기 때문에, 일단 바로 재귀함수를 써보았다.


#include <cstdio>
int func(int arr[][101], int x, int y, int N){
	int ans=0;
	if(x==N && y==N)
		return 1;
	if(x+arr[x][y]<=N)
		ans += func(arr, x+arr[x][y], y, N);
	if(y+arr[x][y]<=N)
		ans += func(arr, x, y+arr[x][y], N);
	return ans;
	
}
int main(void){
	int N;
	scanf("%d",&N);
	int game[101][101]={};
	for(int i=1; i<=N; i++){
		for(int j=1; j<=N; j++){
			scanf(" %d",&game[i][j]);
		}
	}//타일 생성
	int ans = func(game, 1, 1, N);
	printf("%d",ans);
}

 

 

 


당연하게도 시간초과가 뜬다. 다이나믹 프로그래밍이라는 카테고리에 맞게 풀어야 조건을 만족시킬 수 있을 것 같다. 규칙 자체는 어렵지 않다. 제일 오른쪽 아래 칸을 1로 채우고, dp[i][j] += dp[i+game[i][j]][j] + dp[i][j+game[i][j]] 이런식으로 오른쪽으로 갔을 때의 경로와 아래로 갔을 때의 경로를 더한 것을 새롭게 dp에 채우면 된다.

2 3 3 1
1 2 1 3
1 2 3 1
3 1 1 0

 

3 1 1 0
3 1 0 0
2 1 0 1
1 1 1 1

 

위가 game의 배열, 아래가 dp의 배열이다. 이런식으로 for문을 두번 돌려, dp를 역순으로 채워 나간다.


#include <cstdio>
int func(int arr[][101], int x, int y, int N){
	int ans=0;
	if(x==N && y==N)
		return 1;
	if(x+arr[x][y]<=N)
		ans += func(arr, x+arr[x][y], y, N);
	if(y+arr[x][y]<=N)
		ans += func(arr, x, y+arr[x][y], N);
	return ans;
	
}
int main(void){
	int N;
	scanf("%d",&N);
	int game[101][101]={};
	for(int i=1; i<=N; i++){
		for(int j=1; j<=N; j++){
			scanf(" %d",&game[i][j]);
		}
	}//타일 생성
	int ans = func(game, 1, 1, N);
	printf("%d",ans);
}

해결!