코딩문제풀이/Baekjoon

[Java] 백준 17070번 : 파이프 옮기기 1

코딩하는 포메라니안 2023. 4. 7. 17:43

문제

https://www.acmicpc.net/problem/17070

 

17070번: 파이프 옮기기 1

유현이가 새 집으로 이사했다. 새 집의 크기는 N×N의 격자판으로 나타낼 수 있고, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 (r, c)로 나타낼 수 있다. 여기서 r은 행의 번호, c는 열의

www.acmicpc.net

 

풀이 과정

처음에, 어차피 왼쪽에서 오른쪽, 위에서 아래로만 움직일 수 있기 때문에 2중 반복문으로 풀 수 있을 것 같았다. 하지만, 방향까지 고려해야 돼서 생각하다가 DFS로 풀었다.

다 풀고나서, 고민하다가 방향마다 따라 결과를 저장해가면 2중 반복문으로 풀 수 있을 것 같아서 다시 풀었다. 결과적으로 속도가 2배 향상되었다.

 

이전 코드 : DFS

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    static int N, result;
    static int[][] map;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        N = Integer.parseInt(br.readLine());
        map = new int[N+1][N+1];

        for(int i=1; i<=N; i++){
            st = new StringTokenizer(br.readLine());
            for(int j=1; j<=N; j++){
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        dfs(1, 2, 0);
        System.out.println(result);
    }

    public static void dfs(int x, int y, int dir){
        if(x>N || y>N || map[x][y] == 1) return;
        if(dir==2 && (map[x-1][y] == 1 || map[x][y-1] == 1)) return;
        if(x==N && y==N){
            result++;
            return;
        }

        switch (dir){
            case 0:
                dfs(x, y+1, 0);
                dfs(x+1, y+1, 2);
                break;
            case 1:
                dfs(x+1, y, 1);
                dfs(x+1, y+1, 2);
                break;
            case 2:
                dfs(x, y+1, 0);
                dfs(x+1, y, 1);
                dfs(x+1, y+1, 2);
        }

    }
}

개선한 코드 : DP

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        int N = Integer.parseInt(br.readLine());
        int[][] map = new int[N+1][N+1];
        int[][][] dp = new int[N+1][N+1][3];//가로, 세로. 대각선

        for(int i=1; i<=N; i++){
            st = new StringTokenizer(br.readLine());
            for(int j=1; j<=N; j++){
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        for(int i=2; i<=N; i++){
            if(map[1][i] == 1) break;
            dp[1][i][0] = 1;
        }

        for(int i=2; i<=N; i++){
            for(int j=2; j<=N; j++) {
                if (map[i][j] == 1) continue;
                dp[i][j][0] = dp[i][j - 1][0] + dp[i][j - 1][2];
                dp[i][j][1] = dp[i - 1][j][1] + dp[i - 1][j][2];
                if (map[i - 1][j] == 1 || map[i][j - 1] == 1) continue;
                dp[i][j][2] = dp[i - 1][j - 1][0] + dp[i - 1][j - 1][1] + dp[i - 1][j - 1][2];
            }
        }

        System.out.println(dp[N][N][0] + dp[N][N][1] + dp[N][N][2]);
    }
}

 

결과