2019. 11. 19. 19:02ㆍ프로그래밍/백준 알고리즘
https://www.acmicpc.net/problem/1890
1890번: 점프
문제 N×N 게임판에 수가 적혀져 있다. 이 게임의 목표는 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 점프를 해서 가는 것이다. 각 칸에 적혀있는 수는 현재 칸에서 갈 수 있는 거리를 의미한다. 반드시 오른쪽이나 아래쪽으로만 이동해야 한다. 0은 더 이상 진행을 막는 종착점이며, 항상 현재 칸에 적혀있는 수만큼 오른쪽이나 아래로 가야 한다. 한 번 점프를 할 때, 방향을 바꾸면 안 된다. 즉, 한 칸에서 오른쪽으로 점프를 하거나, 아래로
www.acmicpc.net
- 백트래킹을 이용한 dp문제.
알고리즘
1. dp배열에 마지막 칸을 1로, 나머지는 0으로 초기화한다.
2. 백트래킹을 활용한 dfs를 사용해서, 방문한적이 있는 노드를 방문한다면, dp[nowY][nowX]+=dp[nextY][nextX]
방문하지 않은 노드라면, 그 지점에서 dfs를 돌려준다.
3. 결국 처음 값 dp[1][1]이 정답으로 도출됨을 알 수 있다.
시간 복잡도
처음에는 그냥 일반적인 dfs를 사용해서 문제를 풀어보았다.
<틀린 소스 코드>
#include <iostream>
//weird code
using namespace std;
int map[101][101];
long long int dp[101][101]={0,};
long long int dim;
int count=0;
void jump(int x,int y,int block)
{
count++;
if(x>dim || y>dim) return;
if(x==dim && y==dim) return;
int kanX=x+block, kanY=y+block;
cout<<"y : "<<y<<" x : "<<x<<endl;
if(kanX<=dim){
dp[y][kanX]+=dp[y][x];
jump(kanX,y,map[y][kanX]);
}
if(kanY<=dim){
dp[kanY][x]+=dp[y][x];
jump(x,kanY,map[kanY][x]);
}
//중복처리를 안함
}
int main()
{
cin>>dim;
for(int i=1;i<=dim;i++){
for(int j=1;j<=dim;j++){
scanf("%lld",&map[i][j]);
}
}
dp[1][1]=1;
jump(1,1,map[1][1]);
for(int i=1;i<=dim;i++){
for(int j=1;j<=dim;j++){
cout<<dp[i][j];
}
cout<<endl;
}
cout<<"count 입니다 "<<count<<endl;
cout<<dp[dim][dim];
}
계속 시간 초과가 나와서, 방문하는 값들을 찾아보니 반복적으로 방문하고 있었다.
그래서 백트래킹을 이용해서 dp를 돌리기로 하였다.
시간 복잡도
map을 입력받는데 O(N) = N^2. 최악의 경우 map에 모든 값이 1인 경우.
점화식 f(n) = f(n-1) + f(n-1), f(0) = 1
예외 조건
map의 값이 0인 경우가 있다. 이때 메모리 초과가 나는데 이 경우를 따로 빼서 처리해야한다.
소스코드
#include <iostream>
using namespace std;
int map[101][101];
long int dp[101][101]={0,};
long int dim;
void jump(int x,int y)
{
int move[2][2]={{map[y][x],0},{0,map[y][x]}};
if(x>dim || y>dim) return;
for(int i=0;i<=1;i++){
long int nextX=move[i][0]+x,nextY=move[i][1]+y;
if(nextX==x && nextY==y) break;
if(dp[nextY][nextX]==0){
jump(nextX,nextY);
}//방문한적 없다면
dp[y][x]+=dp[nextY][nextX];
//방문 했었다면
}
}
int main()
{
scanf("%d",&dim);
for(int i=1;i<=dim;i++){
for(int j=1;j<=dim;j++){
scanf("%lld",&map[i][j]);
}
}
dp[dim][dim]=1;
jump(1,1);
printf("%ld",dp[1][1]);
}
틀린 내용이나 지적 언제나 환영입니다.
도움이 되었다면 하트 한번씩 눌러주세요:)
'프로그래밍 > 백준 알고리즘' 카테고리의 다른 글
백준 알고리즘 풀이 10942번 - 팰린드롬? (0) | 2020.05.19 |
---|---|
백준 알고리즘 풀이 1107번 - 리모컨 (0) | 2020.05.14 |
백준 알고리즘 풀이 11404번 - 플로이드 (0) | 2019.10.28 |
백준 알고리즘 풀이 1915번 - 가장 큰 정사각형 (0) | 2019.10.15 |
백준 알고리즘 풀이 13458번 - 시험 감독 (0) | 2019.10.10 |