Search
Duplicate

파이프 옮기기 1

주차
0주차
문제번호
17070
언어
티어
골드
유형
DP
그래프
nj_Blog
nj_상태
이해도
풀이
사람
이해도 2
13 more properties

Memo

어려웠던 점

처음에 완전 탐색으로 풀었는데 시간 초과가 나서 dp로 바꿔 풀었습니다. dp로 풀기 위해서는 파이프가 총 3방향으로 놓일 수 있기 때문에 3차원 배열로 풀어야 한다는 사실을 인지하는 것 까지가 어려웠습니다 (저는 이차원 배열 3개로 . 또한 파이프가 두 칸을 차지하기 때문에 어디에 값을 저장해야 하는지에 대한 고민도 필요했습니다. 삼성 기출문제들은 그냥 막 구현하면 될 것 같지만 생각을 좀 더 해보면 당연한 규칙들이 나오기 때문에 좀 더 깊게 고민해야 하는 것 같습니다.

아쉬웠던 점

이차원 배열을 반복문으로 돌면서 dp를 이용할 수 있는데, 그래프를 통해 풀어서 그런지 시간이 상당히 많이 소요되었습니다.
dfs함수 내에서 코드가 가독성이 떨어졌습니다.

Code

제출 날짜

@3/1/2021

메모리

2024KB

시간

664ms
#include <iostream> #include <vector> std::vector<std::vector<int> >pipe; std::vector<std::vector<int> >dp_right; std::vector<std::vector<int> >dp_down; std::vector<std::vector<int> >dp_diagonal; int N; size_t _N; int cnt; std::vector<std::vector<std::pair<int, int> > >g_right_dir; std::vector<std::pair<int, int> >g_left_dir; void input_faster() { std::ios_base::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); } void input() { input_faster(); std::cin >> N; pipe.resize(N, std::vector<int>(N)); dp_right.resize(N, std::vector<int>(N)); dp_down.resize(N, std::vector<int>(N)); dp_diagonal.resize(N, std::vector<int>(N)); _N = N; for (size_t i = 0 ; i < _N ; i++) for (size_t j = 0 ; j < _N ; j++) std::cin >> pipe[i][j]; cnt = 0; g_right_dir = {{{0, 1}, {1, 1}},{{1, 0}, {1, 1}}, {{1, 0}, {1, 1}, {0, 1}}}; g_left_dir = {{0, 1} , {1, 0}, {1, 1}}; } int dir_check(std::pair<int, int> left, std::pair<int, int> right) { if (right.first == left.first && right.second > left.second) return (1); else if (right.first > left.first && right.second == left.second) return (2); else return (3); } int dir_distribute_right(int a) { if (a == 1) return (0); else if (a == 2) return (1); else return (2); } int dir_distribute_left(int a) { if (a == 1) return (0); else if (a == 2) return (1); else return (2); } int dfs(std::pair<int, int> left, std::pair<int, int> right) { if (right.first >= N || right.second >= N || pipe[right.first][right.second]) return (0); int dir = dir_check(left, right); if (dir == 3) if (pipe[right.first - 1][right.second] || pipe[right.first][right.second - 1]) return (0); if (right.first == N - 1 && right.second == N - 1) return (1); std::pair<int, int> dfs_left, dfs_right; std::vector<std::pair<int, int> > dir_right = g_right_dir[dir_distribute_right(dir)]; std::pair<int, int> dir_left = g_left_dir[dir_distribute_left(dir)]; dfs_left.first = left.first + dir_left.first; dfs_left.second = left.second + dir_left.second; int rtn_val = 0; for (size_t i = 0 ; i < dir_right.size(); i++) { dfs_right.first = right.first + dir_right[i].first; dfs_right.second = right.second + dir_right[i].second; int dp_dir = dir_check(dfs_left, dfs_right); if (dp_dir == 1) { if (dp_right[right.first][right.second]) rtn_val += dp_right[right.first][right.second]; else rtn_val += (dp_right[right.first][right.second] = dfs(dfs_left, dfs_right)); } else if (dp_dir == 2) { if (dp_down[right.first][right.second]) rtn_val += dp_down[right.first][right.second]; else rtn_val += (dp_down[right.first][right.second] = dfs(dfs_left, dfs_right)); } else { if (dp_diagonal[right.first][right.second]) rtn_val += dp_diagonal[right.first][right.second]; else rtn_val += (dp_diagonal[right.first][right.second] = dfs(dfs_left, dfs_right)); } } return (rtn_val); } void solve() { std::cout << dfs({0,0},{0,1}); } int main() { input(); solve(); return (0); }
C++
복사