※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 17069번 문제인 파이프 옮기기 2이다.
문제는 아래 링크를 확인하자.
17069번: 파이프 옮기기 2
유현이가 새 집으로 이사했다. 새 집의 크기는 N×N의 격자판으로 나타낼 수 있고, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 (r, c)로 나타낼 수 있다. 여기서 r은 행의 번호, c는 열의
www.acmicpc.net
이 문제는 DP를 이용하여 해결할 수 있다. 각 집에 대응되는 칸에 그 점까지 들어오는 가로방향 파이프의 수, 세로방향 파이프의 수, 대각선방향 파이프의 수를 하나하나 기록해나가는 것이다. 기록이 끝나면 N행N열에 적힌 세 방향의 파이프의 개수의 합을 출력한다.
자세하게 쓰면 다음과 같다.
0) 각 집의 정보(빈 칸, 벽), 각 칸까지의 가로, 세로, 대각선으로 끝난 파이프 개수의 정보를 담을 배열을 만든다.
글쓴이는 각 i행j열의 성분에 크기 4의 배열을 주어 각 성분에 위의 내용을 담았다.
1) (1,2) 지점에 가로방향으로 끝나는 파이프가 하나 있다는 초기값을 입력한다.
2) 각 (i,j) 지점에서 윗 행에서 아래 행 방향으로, 같은 행 안에서는 왼쪽 열에서 오른쪽 열 방향으로 다음을 계산한다.
2-0) (i,j) 지점에 벽이 있다면 이 지점에 대한 조사를 건너뛴다.
2-1) (i,j) 지점에서 가로방향으로 끝날 수 있는 경우의 수를 기록한다.
이는 (i,j-1) 지점에서 가로방향으로 끝난 파이프 수와 대각선방향으로 끝난 파이프 수의 합과 같다.
2-2) (i,j) 지점에서 세로방향으로 끝날 수 있는 경우의 수를 기록한다.
이는 (i-1,j) 지점에서 세로방향으로 끝난 파이프 수와 대각선방향으로 끝난 파이프 수의 합과 같다.
2-3) (i,j) 지점에서 대각선방향으로 끝날 수 있는 경우의 수를 기록한다.
이는 (i-1,j-1) 지점에서 가로, 세로방향으로 끝난 파이프 수와 대각선방향으로 끝난 파이프 수의 합과 같다.
만약 (i,j-1) 지점이나 (i-1,j) 지점에 벽이 있다면 이 과정을 생략한다.
3) (N,N) 지점에서 가로, 세로, 대각선 방향으로 끝난 파이프 수의 합을 구해 출력한다. 답이 int 범위를 넘어서는 경우가 있으니 long long을 이용하자.
2-1과 2-2에서, 각 방향의 점이 벽인지 검사를 하지 않은 이유는 그 칸이 벽이라면 자연스럽게 0으로 채워지기 때문이다.
첫 행의 경우 그 위에 0으로 찬 행을 하나 만들면 위 알고리즘이 오류 없이 돌아갈 것이라는 것을 확인할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
using std::cin;
using std::cout;
typedef long long ll;
ll house[33][33][4]; // house[][][0] : 원래 집, 1 2 3 : 그 점으로 끝나는 가로/세로/대각선 파이프 수
int main()
{
int N; cin >> N;
for (int i = 1;i <= N;i++) {
for (int j = 1;j <= N;j++) {
ll x; cin >> x;
house[i][j][0] = x;
}
}
house[1][2][1] = 1;
for (int i = 1;i <= N;i++) {
for (int j = 2;j <= N;j++) {
if (i == 1 and j == 2) continue;
if (house[i][j][0] == 1) continue;
house[i][j][1] += house[i][j - 1][1] + house[i][j - 1][3];
house[i][j][2] += house[i - 1][j][2] + house[i - 1][j][3];
if (!(house[i - 1][j][0] == 1) and !(house[i][j - 1][0] == 1)) {
house[i][j][3] += house[i - 1][j - 1][1] + house[i - 1][j - 1][2] + house[i - 1][j - 1][3];
}
}
}
cout << house[N][N][1] + house[N][N][2] + house[N][N][3];
return 0;
}'BOJ' 카테고리의 다른 글
| [BOJ 15685 // C++] 드래곤 커브 (0) | 2021.02.20 |
|---|---|
| [BOJ 14888 // C++] 연산자 끼워넣기 (0) | 2021.02.19 |
| [BOJ 9935 // C++] 문자열 폭발 (0) | 2021.02.17 |
| [BOJ 15483 // C++] 최소 편집 (0) | 2021.02.16 |
| [BOJ 14503 // C++] 로봇 청소기 (0) | 2021.02.15 |