문제 출처: https://www.acmicpc.net/problem/17070


풀이

주어진조건을 이용하여 모든 가능한 경우를 탐색하는 완전탐색 문제입니다.

파이프가 가로방향일 때는 오른쪽과 대각선, 세로방향일 때는 세로방향과 대각선, 대각선 방향일 때는 오른쪽+대각선+세로 모두 이동가능합니다.

이 조건을 이용하여 중요한 부분들을 적어보았습니다.


1. 방향배열(dx,dy)의 요소는 4개가 아니라 3개입니다.(서쪽방향이없음)

2. 파이프끝의 좌표와 현재 방향을 시작으로 dfs연산을 합니다.

3. dfs내부에서 y==n-1&&x==n-1이면 파이프가 끝에 도착한것이므로 경우의수를++해주고 종료합니다.

4. 파이프가 움직일 수 있는 경우에 대해서만 연산 할 수 있게 코드를 작성합니다.

문제에서 주어진 조건 순서대로 파이프가 가로방향일 때, 세로방향일 때, 대각선 방향일 때 움직일 수 있는 경우만 계산합니다.

중요한것은, 대각선 방향일 때, 파이프가 동쪽,남쪽,대각선방향 3칸을 차지하므로, 동쪽,남쪽방향이 벽일 때를 고려해줘야합니다

(대각선 방향일 때는 ny,nx로 다음 방향들을 탐색 할 때 if(map[ny][nx]!=1)의 조건에의해 검사됩니다.)


그리고, 구현할 때 굳이 파이프의 방향변수를 선언하여 걍 방향별로 연산을하는 번거로운 코드들을 작성하지않아도됩니다.

왜냐하면 dfs함수 내부에서 한번 연산 할 때 방향별로(동,대각,아래) 한번 씩 수행되기 때문에, 방향별로 탐색하는 for문의 i가 파이프의 방향을 나타내기도 하기 때문입니다. 

만약 pipe변수를 선언하여 0(동쪽)일때, 1(대각선), 2(아래)에 대해 각각 계산하고자 했다면 코드가 길어졌을겁니다. 


코드

#include<iostream>
using namespace std;
int n;
int map[16][16];
//동 대각선,아래
int dx[3] = { 1,1,0 };
int dy[3] = { 0,1,1 };
//파이프방향
int ans;
void dfs(int y, int x, int dir);
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> map[i][j];
	///3번쨰 인자는 파이프방향임(0:동:1:대각2:남)
	dfs(0, 1, 0);
	cout << ans << '\n';
}
void dfs(int y, int x, int dir)
{
	if (y == n - 1 && x == n - 1)
	{
		ans++;
		return;
	}
	//3방향에대해 검색
	for (int i = 0; i < 3; i++)
	{
		//파이프가 가로면 가로+대각선만계산
		if (dir == 0 && i == 2)continue;
		//파이프가 세로면 세로+대각선만계산
		if (dir == 2 && i == 0)continue;
		//대각선일 때
		if (i == 1 && (map[y][x + 1] == 1 || map[y + 1][x] == 1))
			continue;

		int ny = y + dy[i];
		int nx = x + dx[i];
		//범위벗어나지않고 이동한 좌표가벽아닐 때
		if (ny < n && nx < n && map[ny][nx] != 1)
			dfs(ny, nx, i);
	}
}


결과

'문제풀이(BOJ) > 삼성 sw역량테스트 기출' 카테고리의 다른 글

[백준 16235] 나무 재테크  (0) 2020.02.02
[백준 14500] 테트로미노  (0) 2020.02.01
[백준 17144] 미세먼지 안녕!  (0) 2020.01.29
[백준 3190] 뱀  (0) 2020.01.29
[백준 14503] 로봇 청소기  (0) 2020.01.28

+ Recent posts