본문 바로가기
알고리즘 문제풀이/백준

[백준 17070] 파이프 옮기기 1

by 선서니 2023. 3. 29.

[문제 바로가기]👇

 

17070번: 파이프 옮기기 1

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

www.acmicpc.net

 

💡풀이💡

현재 파이프의 방향과 위치에 따라 이동 가능한 곳이 정해져 있음!

  • 특별하게 알 수 있는 방법이 없다고 판단했기 때문에 완전 탐색 진행
  • 한 방향으로 갈 수 있는 방법을 모두 가고 그 길이 안되면 다시 돌아와서 다음 방향 탐색
    >> dfs

 

1. 입력 받기

	static int N, ans;
	static int[][] map;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		map = new int[N][N];
		for(int i=0; i<N; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			for(int j=0; j<N; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		br.close();
}

 

2. DFS를 이용한 완전 탐색

dfs의 파라미터로 현재 파이프의 정보를 넘기면서 파이프를 밀어서 이동할 때마다 파이프의 정보를 갱신한다

현재 파이프의 방향에 따라 이동할 수 있는 방법이 다르기 때문에 가능한 방향으로 모두 이동해보도록 구현

dfs(0,0,0,1,0);
System.out.println(ans);

//startR : 파이프의 시작 r위치, startC : 파이프의 시작 c위치, endR : 파이프의 끝 r위치, endC : 파이프의 끝 c위치
//dir : 파이프의 방향
static void dfs(int startR, int startC, int endR, int endC, int dir) {
		if(endR==N-1 && endC==N-1) { // 파이프가 끝에 도달했다면
			ans++;
			return;
		}
		
		// 파이프가 현재 가로방향이면
		if(dir==0) {
			//오른쪽으로 이동
			if(endC+1<N && map[endR][endC+1]!=1) {
				dfs(startR, startC+1, endR, endC+1, 0);
			}
			
			//오른쪽 아래 대각선으로 이동
			if(endR+1<N && endC+1<N) {
				if(map[endR+1][endC]!=1 && map[endR][endC+1]!=1 && map[endR+1][endC+1]!=1)
					dfs(startR, startC+1, endR+1, endC+1, 2);
			}
		}
		// 파이프가 현재 세로방향이면
		else if(dir==1) {
			//아래로 이동
			if(endR+1<N && map[endR+1][endC]!=1) {
				dfs(startR+1, startC, endR+1, endC, 1);
			}
			
			//오른쪽 아래 대각선으로 이동
			if(endR+1<N && endC+1<N) {
				if(map[endR+1][endC]!=1 && map[endR][endC+1]!=1 && map[endR+1][endC+1]!=1)
					dfs(startR+1, startC, endR+1, endC+1, 2);
			}
		}
		// 파이프가 현재 대각선방향이면
		else if(dir==2) {
			//오른쪽으로 이동
			if(endC+1<N && map[endR][endC+1]!=1) {
				dfs(startR+1, startC+1, endR, endC+1, 0);
			}
			
			//아래로 이동
			if(endR+1<N && map[endR+1][endC]!=1) {
				dfs(startR+1, startC+1, endR+1, endC, 1);
			}
			
			//오른쪽 아래 대각선으로 이동
			if(endR+1<N && endC+1<N) {
				if(map[endR+1][endC]!=1 && map[endR][endC+1]!=1 && map[endR+1][endC+1]!=1)
					dfs(startR+1, startC+1, endR+1, endC+1, 2);
			}
		}
	}

 

전체 코드

package Day_0329;

import java.io.*;
import java.util.*;

public class B17070 {
	static int N, ans;
	static int[][] map;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		map = new int[N][N];
		for(int i=0; i<N; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			for(int j=0; j<N; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		dfs(0,0,0,1,0);
		System.out.println(ans);
		br.close();
	}
	
	//startR : 파이프의 시작 r위치, startC : 파이프의 시작 c위치, endR : 파이프의 끝 r위치, endC : 파이프의 끝 c위치
	//dir : 파이프의 방향
	static void dfs(int startR, int startC, int endR, int endC, int dir) {
		if(endR==N-1 && endC==N-1) { // 파이프가 끝에 도달했다면
			ans++;
			return;
		}
		
		// 파이프가 현재 가로방향이면
		if(dir==0) {
			//오른쪽으로 이동
			if(endC+1<N && map[endR][endC+1]!=1) {
				dfs(startR, startC+1, endR, endC+1, 0);
			}
			
			//오른쪽 아래 대각선으로 이동
			if(endR+1<N && endC+1<N) {
				if(map[endR+1][endC]!=1 && map[endR][endC+1]!=1 && map[endR+1][endC+1]!=1)
					dfs(startR, startC+1, endR+1, endC+1, 2);
			}
		}
		// 파이프가 현재 세로방향이면
		else if(dir==1) {
			//아래로 이동
			if(endR+1<N && map[endR+1][endC]!=1) {
				dfs(startR+1, startC, endR+1, endC, 1);
			}
			
			//오른쪽 아래 대각선으로 이동
			if(endR+1<N && endC+1<N) {
				if(map[endR+1][endC]!=1 && map[endR][endC+1]!=1 && map[endR+1][endC+1]!=1)
					dfs(startR+1, startC, endR+1, endC+1, 2);
			}
		}
		// 파이프가 현재 대각선방향이면
		else if(dir==2) {
			//오른쪽으로 이동
			if(endC+1<N && map[endR][endC+1]!=1) {
				dfs(startR+1, startC+1, endR, endC+1, 0);
			}
			
			//아래로 이동
			if(endR+1<N && map[endR+1][endC]!=1) {
				dfs(startR+1, startC+1, endR+1, endC, 1);
			}
			
			//오른쪽 아래 대각선으로 이동
			if(endR+1<N && endC+1<N) {
				if(map[endR+1][endC]!=1 && map[endR][endC+1]!=1 && map[endR+1][endC+1]!=1)
					dfs(startR+1, startC+1, endR+1, endC+1, 2);
			}
		}
	}

}

 

문제 리뷰

📌놓쳤던 부분

문제에 있는 예제 입력 3번의 답은 0인데 계속 5가 나왔다…

분명 로직에 문제가 있는 건데 어디가 문제인지 몰라서 문제를 다시 읽어보다가 파이프를 이동시킬 때 파이프를 미는 방향에 따라 꼭 빈 칸이어야 하는 곳이 있다는 걸 알게 됐다..😱😱😱😱

 

📌실수했던 부분

파라미터가 많고 조건에 따라 파이프의 시작 위치, 끝 위치를 다 다르게 바꿔줘야 하다보니까

많이 헷갈렸고 한 눈에 안 들어왔다..

그러다보니 이동할 때 파라미터 값을 잘못 넘겨준게 있어서 틀렸었다..

놓친 부분이 아니라 아는데 실수한 거라서 어떻게 보면 더 찾기 힘들었을 것 같은 부분이었다..

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 9205] 맥주 마시면서 걸어가기  (0) 2023.04.03
[백준 14502] 연구소  (0) 2023.03.30
[백준 10971] 외판원 순회 2  (0) 2023.03.29
[백준 1463] 1로 만들기  (0) 2023.03.28
[백준 11727] 2xn 타일링 2  (0) 2023.03.28

댓글