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);
}
해결!
'알고리즘 문제' 카테고리의 다른 글
[C/C++ 백준 11052번] 카드구매하기 (Silver 1) (0) | 2020.05.09 |
---|---|
[C/C++ 백준 1660번] 캡틴 이다솜 (Silver 2) (0) | 2020.05.07 |
[C/C++ 백준 2133번] 타일 채우기 (Silver 2) (0) | 2020.05.06 |
[C/C++ 백준 11727번] 2×n 타일링 2 (Silver 3) (0) | 2020.05.06 |
[C/C++ 백준 11726번] 2×n 타일링 (Silver 3) (0) | 2020.05.06 |