티스토리 뷰
문제
16973번: 직사각형 탈출
크기가 N×M인 격자판에 크기가 H×W인 직사각형이 놓여 있다. 격자판은 크기가 1×1인 칸으로 나누어져 있다. 격자판의 가장 왼쪽 위 칸은 (1, 1), 가장 오른쪽 아래 칸은 (N, M)이다. 직사각형의 가장
www.acmicpc.net
풀이
1. 간단하게 생각해본다면 시작 점에서부터 BFS를 돌려 "왼쪽 위 점에서부터 오른쪽 아래 점까지 1이 포함되어 있는가?"를 확인하며 진행하면 될 것 같지만 $O(n*m*h*w)$로 시간 초과가 납니다.
2. "해당 점에서 부터 오른쪽 아래 점까지 1이 포함되어 있는가?"를 연산하며 중복된 칸을 계속 탐색하므로 이를 막기 위해 dp를 사용합니다. 이때 상태 정의는 "dp[i][j] = (0, 0)부터 (i, j)칸 까지 1의 개수의 합(누적합)"이며 첫 행과 첫 열을 누적해놓은 상태에서 상태 전이는 일반적인 2차원 누적합과 같습니다. $$ dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][ j - 1] + g[i - 1][j - 1] $$
3. 이제 "왼쪽 위 점에서 부터 오른쪽 아래 점까지 1이 포함되어 있는가?"는 왼쪽 위 점을 (a, b), 오른쪽 아래 점을 (c, d)라 할 때 아래와 같이 1의 개수를 $O(1)$에 구할 수 있습니다.
코드
#include <bits/stdc++.h>
using namespace std;
const int dir[4][2] = { { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 } };
int n, m, h, w, g[1001][1001], dp[1001][1001], sr, sc, dr, dc;
bool vis[1001][1001];
int go(int r, int c) {
if (r < 0 || c < 0) return 0;
int& ret = dp[r][c];
if (ret != -1) return ret;
return ret = go(r - 1, c) + go(r, c - 1) - go(r - 1, c - 1) + g[r][c];
}
void bfs() {
int cr, cc, nr, nc, cost, cnt, a, b, c, d;
queue<tuple<int, int, int>> q;
vis[sr][sc] = 1;
q.push({ sr,sc,0 });
while (!q.empty()) {
tie(cr, cc, cost) = q.front(); q.pop();
if (cr == dr && cc == dc) {
cout << cost;
return;
}
for (int i = 0; i < 4; i++) {
nr = cr + dir[i][0], nc = cc + dir[i][1];
if (nr < 0 || nr >= n || nc < 0 || nc >= m || vis[nr][nc] || g[nr][nc] || nr + h - 1 >= n || nc + w - 1 >= m) continue;
a = nr, b = nc, c = nr + h - 1, d = nc + w - 1;
cnt = go(c, d) - go(a - 1, d) - go(c, b - 1) + go(a - 1, b - 1);
if (cnt) continue;
vis[nr][nc] = 1;
q.push({ nr,nc,cost + 1 });
}
}
cout << -1;
}
int main() {
cin.tie(NULL); cout.tie(NULL);
ios_base::sync_with_stdio(false);
memset(dp, -1, sizeof(dp));
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> g[i][j];
dp[0][0] = g[0][0];
for (int i = 1; i < n; i++) dp[i][0] = dp[i - 1][0] + g[i][0];
for (int i = 1; i < m; i++) dp[0][i] = dp[0][i - 1] + g[0][i];
cin >> h >> w >> sr >> sc >> dr >> dc;
sr--, sc--, dr--, dc--;
bfs();
}
'Algorithm > BOJ' 카테고리의 다른 글
[백준 20435] ZOAC3 (0) | 2021.01.08 |
---|---|
[백준 3109] 빵집 (0) | 2021.01.08 |
[백준 3020] 개똥벌레 (0) | 2021.01.04 |
[백준 10775] 공항 (0) | 2020.12.19 |
[백준 14939] 불끄기 (0) | 2020.12.19 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 투포인터
- 동적계획법
- Kakaoblind
- 2022 카카오블라인드
- 카카오 2020 인턴십
- 2020 KAKAO BLIND RECRUITMENT
- 카카오 2021
- 위클리 챌린지
- 트리
- 카카오 표 편집
- 누적합
- DP
- 백준
- 프로그래머스
- BFS
- 표 편집
- 2021 카카오 블라인드
- 구현
- 2022 카카오 블라인드 코딩테스트
- 시뮬레이션
- 카카오 인턴십
- 2022 KAKAO BLIND RECRUITMENT
- 2021 KAKAO BLIND
- 파싱
- 게임이론
- 유니온파인드
- 프로그래머스 월간코드챌린지
- 프로그래머스 위클리 9주차
- 이분탐색
- 카카오 2차코딩테스트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함