거의 알고리즘 일기장
백준 1520번 _ 내리막 길 본문
https://www.acmicpc.net/problem/1520
1520번: 내리막 길
여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으며, 각 지점 사이의 이동은 지도에서 상하좌우 이웃한 곳끼리만 가능하다. 현재 제일 왼쪽 위 칸이 나타내는 지점에 있는 세준이는 제일 오른쪽 아래 칸이 나타내는 지점으로 가려고 한다. 그런데 가능한 힘을 적게 들이고 싶어 항상 높이가 더 낮은 지점으로만 이동하여 목표 지
www.acmicpc.net
접근
주어진 조건들을 먼저보자.
시간은 2초, MxN 행렬 (M, N <=500), 다음 위치는 현재위치보다 무조건 낮다.
먼저 생각해 볼수 있는건 DFS다. 그런데 잘 생각해보면 이게 방향이 우측, 아래로만 간다는 조건도 없고 사방으로 갈수있기 때문에 대충 생각해봐도 시간오바다. ( 계산을 해서 보여주고 싶지만... 어떻게 계산해야될지도 모르겠다. 하지만, 2초라는 시간 안에는 수행할수 없다는것은 당연히 직관적으로 이해될 것임으로 넘어가겠다. )
그렇다면 시간을 줄여야 할까?
잘 생각해보면 도착점까지 간 경로에 포함된 곳에 다시 가는것은 시간낭비라는것을 알수있다. (이해가 안된다면 밑에 그림 참조)
풀이방법
정답부터 말하자면 DFS에 DP를 더해서 푸는 방법으로 풀 수있는 문제다.
그렇다면 어떻게 DP를 적용할수 있을까?
바로 도착점에 도달했던 경로에 겹치게 되면 바로 RETURN시켜 필요없는 연산을 하지 않는것이다. ( 가지치기 )
DP[i][j] : i, j 지점에서 도착지점까지 갈수있는 경로의 개수 , 처음에 가보지 않은 지점은 -1로 초기화 할것.
(동작에 대한 GIF가 있으니 밑의 블로그에서 보면 이해가 빠를것이다.)
https://wootool.tistory.com/83
[백준][1520번][DP] 내리막길
내리막길 https://www.acmicpc.net/problem/1520 <코드> 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51..
wootool.tistory.com
전체코드
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int map[501][501];
int visited[501][501];
int M, N;
int dy[] = { -1, 1, 0, 0 };
int dx[] = { 0, 0, -1, 1 };
void visitedInit()
{
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
visited[i][j] = -1;
}
void Input()
{
cin >> M >> N;
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
cin >> map[i][j];
}
}
}
bool inRange(int y, int x)
{
if (y >= 0 && x >= 0 && y < M && x < N)
return true;
return false;
}
int dfs(int y, int x)
{
//목적지 도착
if (y == M - 1 && x == N - 1)
return 1;
//이미 도착점에 도착했던 경로가 있을때
if (visited[y][x]!=-1)
return visited[y][x];
visited[y][x] = 0;
for (int i = 0; i < 4; i++)
{
int ny = y + dy[i];
int nx = x + dx[i];
if (inRange(ny, nx) == false)
continue;
//항상 더 낮은 지점으로만 움직일수 있다.
if (map[y][x] <= map[ny][nx])
continue;
visited[y][x] += dfs(ny, nx);
}
return visited[y][x];
}
int main()
{
Input();
visitedInit();
cout << dfs(0, 0);
return 0;
}
후기
비슷한 카카오 문제를 풀어본적 있는데 그것과는 다른 방식으로 문제를 풀었다.
'알고리즘 문제풀이' 카테고리의 다른 글
백준 10942번 _ 팰린드롬? (0) | 2020.05.05 |
---|---|
백준 7579번 _ 앱 (0) | 2020.05.05 |
백준 11049번 _ 행렬 곱셈 순서 (0) | 2020.05.04 |
백준 11066번 _ 파일 합치기 (1) | 2020.05.04 |
백준 2293번 _ 동전 1 (0) | 2020.05.03 |