BOJ 1513 - 경로 찾기
문제
N
x M
크기인 지도에 1
부터 C
까지 번호가 매겨진 오락실 C
개가 존재한다.
직전에 방문한 오락실의 번호가 이번에 방문할 오락실의 번호보다 작은 경우 방문할 수 있다.
이때 (1, 1)
에서 출발하여 (N, M)
으로 가는 경로들 중 오락실을 [1, C]
개 지나는 경로의 개수를 각각 출력하면 된다.
풀이
dp를 아래와 같이 설계한다.
dp(i
)(j
)(c
)(p
) = (i, j)
의 좌표에 위치하고 현재까지 방문한 오락실의 개수가 c
개이며 가장 최근에 방문한 오락실의 번호가 p
인 경로의 개수
이때 아래와 같이 점화식을 구할 수 있다.
(i, j)
가 오락실일 경우
dp(i
)(j
)(c
)(p
)=dp(i-1
)(j
)(c-1
)([0, p-1]
) + dp(i
)(j-1
)(c-1
)([0, p-1]
)- 현재 위치가 오락실이기 때문에 방문한 오락실 수
c
는 1이 증가하고 가장 최근의 오락실의 위치는p
로 초기화됨
- 현재 위치가 오락실이기 때문에 방문한 오락실 수
(i, j)
가 오락실이 아닐 경우
dp(i
)(j
)(c
)(p
)=dp(i-1
)(j
)(c
)(p
)+dp(i
)(j-1
)(c
)(p
)- 가능한 경로만 계산해주면 됨
(1, 1)
도 오락실이 될 수 있기 때문에 (1, 1)
이 k
번째 오락실일 경우 dp(1
)(1
)(1
)(k
)=1
로 초기화하고,
오락실이 아닐 경우 dp(1
)(1
)(0
)(0
)=1
로 초기화한다.
소스코드
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
#define MOD 1000007
using namespace std;
using pii=pair<int, int>;
using vi=vector<int>;
using vl=vector<long long>;
using lld=long long;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n, m, c;
cin>>n>>m>>c;
vector<vi> ar(n, vi(m, 0));
vector<vector<vector<vl> > > dp(n, vector<vector<vl> >(m, vector<vl>(c+1, vl(c+1, 0))));
for(int i=0;i<c;i++){
int r, cc;
cin>>r>>cc;
ar[r-1][cc-1]=i+1;
}
if(ar[0][0]) dp[0][0][1][ar[0][0]]=1;
else dp[0][0][0][0]=1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(ar[i][j]){
int curc=ar[i][j];
if(i>0){
for(int k=0;k<curc;k++){
for(int l=0;l<curc;l++){
dp[i][j][k+1][curc]+=dp[i-1][j][k][l];
dp[i][j][k+1][curc]%=MOD;
}
}
}
if(j>0){
for(int k=0;k<curc;k++){
for(int l=0;l<curc;l++){
dp[i][j][k+1][curc]+=dp[i][j-1][k][l];
dp[i][j][k+1][curc]%=MOD;
}
}
}
}
else{
if(i>0){
for(int k=0;k<=c;k++){
for(int l=0;l<=c;l++){
dp[i][j][k][l]+=dp[i-1][j][k][l];
dp[i][j][k][l]%=MOD;
}
}
}
if(j>0){
for(int k=0;k<=c;k++){
for(int l=0;l<=c;l++){
dp[i][j][k][l]+=dp[i][j-1][k][l];
dp[i][j][k][l]%=MOD;
}
}
}
}
}
}
for(int i=0;i<=c;i++){
int ans=0;
for(int j=0;j<=c;j++){
ans+=dp[n-1][m-1][i][j];
ans%=MOD;
}
cout<<ans<<' ';
}
return 0;
}
- 좌표는 편의상
[0, n-1]
,[0, m-1]
을 사용하였다.
풀고나서
- 상태공간이 4개가 넘어가면 데이터의 크기도 작아지는데, 이것을 이용해서 풀이 방법이 dp라고 유추할 수도 있을 것 같다.
Leave a comment