Algorithm

[BOJ] 17069. 파이프 옮기기 2

프로그래민 2020. 5. 30. 14:46
반응형

이 문제는 DP로 해결하였다.

맨 처음 문제를 봤을때 재귀적인 그래프의 탐색형태로 접근하려고 했다. 하지만 N의 크기가 재귀를 사용하기에 너무 큰 경우의 수를 가지기에 재귀말고 DP로 접근하게 되었다. 일단 모든 맵의 칸에서 3가지의 경우의수를 가지고 했다. 파이프가 각각 가로,세로,대각선으로 깔리게 되는 3가지로 두었다. 그리고 만일 i,j에서 가로로깔리게 되는 경우의 수를 생각해보면 i-1,j 에서의 가로와 대각선의 경우의 수를 가질수 있게 된다. 이러한 방식으로 다음과 같이 생각하게 되었다.

1) i,j에서 가로의 파이프를 가지는 경우 : (i-1,j에서 가로) + (i-1,j에서 대각선)
2) i,j에서 세로의 파이프를 가지는 경우 : (i,j-1에서 세로) + (i,j-1에서 대각선)
3) i,j에서 대각선의 파이프를 가지는 경우 : (i-1,j-1에서 가로) + (i-1,j-1에서 세로) + (i-1,j-1에서 대각선)
이러한 규칙으로 벽(1) 이 아닐때를 구하게 되었다.

DP를 오랜만에 풀어보느라 점화식을 세움에 있어 어려움이 많았다. 한번더 생각해보는 습관이 필요한 거 같다.

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
package boj2;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_bj_17069_파이프옮기기2 {
    static int[][] map;
    static long[][][] count;
    
    static int N;
    
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;
        N=Integer.parseInt(br.readLine());
        map=new int[N][N];
        for(int i=0;i<N;i++) {
            st=new StringTokenizer(br.readLine());
            for(int j=0;j<N;j++) {
                map[i][j]=Integer.parseInt(st.nextToken());
            }
        }
        
        count=new long[N][N][3];
        init();
 
        
        dp();
        
        long answer=0;
        
        
        for(int i=0;i<3;i++)
            answer+=count[N-1][N-1][i];
        System.out.println(answer);
        
    }
    
    static void init() {
        for(int i=1;i<N;i++) {
            if(map[0][i]==0) {
                count[0][i][0]=1;        // 오른쪽방향 1로 셋팅
            }else {
                break;
            }
        }
    }
    
    static void dp() {
        for(int i=1;i<N;i++) {
            for(int j=2;j<N;j++) {
                if(map[i][j]==0) {
                    if(map[i][j-1]==0)
                        count[i][j][0]=count[i][j-1][0]+count[i][j-1][2];
                    if(map[i-1][j]==0)
                        count[i][j][1]=count[i-1][j][1]+count[i-1][j][2];
                    if(map[i-1][j-1]==0 && map[i-1][j]==0 && map[i][j-1]==0)
                        count[i][j][2]=count[i-1][j-1][0]+count[i-1][j-1][1]+count[i-1][j-1][2];
                    
                }
            }
        }
    }
    
    
}
 
                         

 

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
78
79
80
package algostudy3;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_bj_17069_파이프옮기기2 {
    static int N;
    static int[][] map;
    static long[][][] dp;
 
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;
 
        N = Integer.parseInt(br.readLine());
 
        map = new int[N][N];
        dp = new long[3][N][N];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
                dp[0][i][j] = -1;
                dp[1][i][j] = -1;
                dp[2][i][j] = -1;
            }
        }
 
        System.out.println(dfs(001));
 
    }
 
    static long dfs(int type, int i, int j) {
        if (i == N - 1 && j == N - 1) {
            return 1;
        }
 
        if (dp[type][i][j] != -1) {
            return dp[type][i][j];
        }
 
        dp[type][i][j] = 0;
 
        if (type == 0) {        //가로인경우
            checkBlockRow(type, i, j);
            checkBlockCross(type, i, j);
        } else if (type == 1) {    //세로인경우
            checkBlockCol(type, i, j);
            checkBlockCross(type, i, j);
        } else if (type == 2) {    //대각인경우
            checkBlockRow(type, i, j);
            checkBlockCol(type, i, j);
            checkBlockCross(type, i, j);
        }
 
        return dp[type][i][j];
    }
 
    static void checkBlockRow(int type, int i, int j) {
        if (j + 1 < N && map[i][j + 1== 0) {
            dp[type][i][j] += dfs(0, i, j + 1);
        }
    }
 
    static void checkBlockCol(int type, int i, int j) {
        if (i + 1 < N && map[i + 1][j] == 0) {
            dp[type][i][j] += dfs(1, i + 1, j);
        }
    }
 
    static void checkBlockCross(int type, int i, int j) {
        if (i + 1 < N && j + 1 < N &&
            map[i + 1][j] == 0 && map[i][j + 1== 0 && map[i + 1][j + 1== 0) {
            dp[type][i][j] += dfs(2, i + 1, j + 1);
        }
    }
}
 
               
반응형

'Algorithm' 카테고리의 다른 글

[BOJ] 2931. 가스관  (0) 2020.06.01
[BOJ] 17471. 게리맨더링  (0) 2020.05.30
[SWEA] 5215. 햄버거 다이어트  (0) 2020.05.29
[SWEA] 3234. 준환이의 양팔저울  (0) 2020.05.29
[BOJ] 17142. 연구소 3  (0) 2020.05.29