17070번: 파이프 옮기기 1
유현이가 새 집으로 이사했다. 새 집의 크기는 N×N의 격자판으로 나타낼 수 있고, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 (r, c)로 나타낼 수 있다. 여기서 r은 행의 번호, c는 열의
www.acmicpc.net
- 파이프는 오른쪽 - 아래쪽 까지 90도 밖에 회전할 수 없기 때문에, 왼쪽 파이프가 끝점에 도달할 일은 없다.
- 파이프를 한번 이동시킬 때, 오른쪽 파이프가 반드시 다음 위치의 왼쪽 파이프가 되기 때문에 왼쪽 파이프에 대한 검사는 할 필요 없다.
- 따라서 점 하나만을 특정 조건에 맞게 (N, N) 까지 도달시키면 된다.
- 이전에 움직였던 방향이 주어지면 점이 다음에 갈 수 있는 방향이 고정적으로 주어졌기 때문에, 모든 방향에 대해서 재귀 호출 하면 된다.
- 인덱스와 벽에 대한 검사만 매번 해준다.
#include <iostream>
using namespace std;
int n, temp;
int map[17][17];
int answer;
void dfs(int row, int col, int state) // 왼쪽 파이프는 항상 유효하기 때문에 고려할 필요 없음, 오른쪽 파이프의 위치만 고려
{
if(map[row][col] == 1) return; // 만약 다음 위치가 벽이면 종료
if(row > n || col > n) return; // 인덱스 초과 시 종료
if(state == 3) // 대각선으로 내려왔을 경우는 위쪽과 왼쪽도 벽일 경우 종료
if(map[row-1][col] == 1 || map[row][col-1] == 1) return;
if((row == n && col == n)) // 만약 끝점에 도달했을 경우는
{ // 경로 카운트 증가시키고 종료
answer++;
return;
}
if(state == 1) // 가로로 왔을 땐
{
dfs(row, col + 1, state); // 두 가지 방법으로 일단 보내봄 (유효성 검사는 앞에서 하므로)
dfs(row + 1, col + 1, 3);
}
else if(state == 2) // 세로
{
dfs(row + 1, col, state);
dfs(row + 1, col + 1, 3);
}
else // 대각선
{
dfs(row, col + 1, 1);
dfs(row + 1, col, 2);
dfs(row + 1, col + 1, 3);
}
}
int main()
{
cin >> n;
for(int r = 1 ; r <= n ; r++)
for(int c = 1 ; c <= n ; c++)
cin >> map[r][c];
// 처음에 (1,1) (1,2) 에서 시작하게 될 경우에는
dfs(1, 3, 1); // 가로로 보내고
dfs(2, 3, 3); // 대각선으로 보낼 수 있다
cout << answer << endl;
}
- 2등 소스코드 참고 : www.acmicpc.net/source/17159943
- 3차원 DP 배열을 사용하여, 가로 세로 대각선 3개에 대해 각각 2차원 배열을 만들었다.
- 반복문 내에서, 각 상태별로 유효성을 검사하며 이전 DP 값을 더해나가는 식이다.
#include <cstdio>
int n, map[17][17];
int dp[3][17][17];
int main()
{
scanf("%d", &n);
for(int r = 1 ; r <= n ; r++)
for(int c = 1 ; c <= n ; c++)
scanf("%d", &map[r][c]);
dp[0][1][2] = 1;
for(int r = 1 ; r <= n ; r++)
{
for(int c = 1 ; c <= n ; c++)
{
if(map[r][c] == 1) continue;
for(int i = 0 ; i < 2 ; i++) dp[0][r][c] += dp[i][r][c-1];
for(int i = 1 ; i < 3 ; i++) dp[2][r][c] += dp[i][r-1][c];
for(int i = 0 ; i < 3 ; i++) if(!map[r-1][c] && !map[r][c-1]) dp[1][r][c] += dp[i][r-1][c-1];
}
}
printf("%d\n", dp[0][n][n] + dp[1][n][n] + dp[2][n][n]);
}
'PS > BOJ' 카테고리의 다른 글
[백준] 1504.cpp : 특정한 최단 경로 (0) | 2020.09.03 |
---|---|
[백준] 17144.cpp : 미세먼지 안녕! (0) | 2020.09.02 |
[백준] 14502.cpp : 연구소 (0) | 2020.08.31 |
[백준] 13549.cpp : 숨바꼭질 3 (0) | 2020.08.30 |
[백준] 12865.cpp : 평범한 배낭 (0) | 2020.08.29 |