728x90
개요
문제 링크
골드 5, 누적합, DP
2차원 구간 내에 존재하는 문자의 개수 구하기
접근
- 2차원 경로탐색 DP와 매우 유사하다. 누적합이라도 결국 인접한 원소를 이용하는 것은 동일해서 DP로 분류했다.
- 우선 기본적인 누적합. 만약 1차원 배열에서 i부터 j까지 누적합을 구한다면 어떻게 할까? sum[1,j] - sum[1,i-1]을 해주면 된다.
- 동일하게 2차원에서 [y1,x1]부터 [y2,x2]까지의 누적합을 구한다면 sum[y2,x2]-sum[y2,x1-1]-sum[y1-1,x2]+sum[y1-1,x1-1]을 해주면 된다. 전체 합-왼쪽까지 합-위까지 합+왼쪽위까지 합을 해주는 것인데, 벤다이어그램을 생각하면 쉽다.
만약 A∪B를 구한다면 A+B-A∩B를 해줘야 한다. 어떤 C가 A,B를 포함한다면 C이면서 A,B가 아닌 부분은 C-(A+B-A∩B)를 해주면 된다.
Pseudo code
for (y = 세로)
for (x = 가로)
dp[y][x] = dp[y-1][x]+dp[y][x-1]-dp[y-1][x-1]
dp[y][x] += J / O / I
answer = dp[y2][x2]
answer -= dp[y2][x1-1] + dp[y1-1][x2] - dp[y1-1][x1-1]
Source code
#include <iostream>
#include <array>
using namespace std;
typedef array<int,4> node;
int main() {
int n, m, k;
cin >> n >> m >> k;
node a[n+1][m+1];
char s[m+1];
for (int i=0; i<=n; i++)
for (int j=0; j<=m; j++)
a[i][j] = {0,0,0,0};
for (int i=1; i<=n; i++) {
scanf("%s", s+1);
for (int j=1; j<=m; j++)
a[i][j][3] = s[j];
}
string b = "JOI";
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
for (int k=0; k<3; k++) {
a[i][j][k] = a[i-1][j][k]+a[i][j-1][k]-a[i-1][j-1][k];
a[i][j][k] += a[i][j][3]==b[k];
}
int x,y,p,q;
for (int i=0; i<k; i++) {
scanf("%d%d%d%d",&y,&x,&p,&q);
x--, y--;
for (int j=0; j<3; j++)
printf("%d ",a[p][q][j]-a[y][q][j]-a[p][x][j]+a[y][x][j]);
printf("\n");
}
}
728x90
'백준브실골 > DP' 카테고리의 다른 글
백준 22968, 균형 (2) | 2023.02.17 |
---|---|
백준 17856, Just Passing Through (0) | 2023.02.17 |
백준 1663, XYZ 문자열 (0) | 2023.02.17 |
백준 13910, 개업 (0) | 2023.02.17 |
백준 14238, 출근 기록 (2) | 2023.02.12 |
백준 27210, 신을 모시는 사당 (0) | 2023.02.12 |
백준 11909, 배열 탈출 (0) | 2023.02.11 |
백준 17265, 나의 인생에는 수학과 함께 (0) | 2023.02.09 |
댓글