두 개의 값만 포함하는 행렬이 있다고 가정합니다. 1과 0. 우리는 모두 1을 포함하는 주어진 행렬에서 부분행렬의 수를 찾아야 합니다. 값을 출력으로 인쇄합니다.
따라서 입력이 다음과 같으면
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
0 | 1 | 0 | 1 |
1 | 1 | 0 | 1 |
그러면 출력은 12가 됩니다.
이 문제를 해결하기 위해 다음 단계를 따릅니다. −
- n :=행렬의 크기
- m :=행렬[0]의 크기
- n+1 x m+1 크기의 배열을 정의합니다.
- 초기화 i의 경우:=0, i
- j 초기화의 경우:=0, j
- 덧셈[i + 1, j + 1] + =행렬[i, j]
- 더하기[i + 1, j + 1] + =더하기[i, j + 1]
- 더하기[i + 1, j + 1] + =더하기[i + 1, j] 더하기
- 추가[i + 1, j + 1] - =더하기[i, j]
- j 초기화의 경우:=0, j
- 다음 부분은 무시하고 다음 반복으로 건너뜁니다.
- p :=0,
- q :=m - j;
- p <=q인 동안 −
- x :=(p + q) / 2
- a :=k * x
- cur :=add[i + k, j + x] - add[i, j + x] - add[i + k, j] + add[i, j]
- cur가 와 같으면 -
- r :=x
- p :=x + 1
- 그렇지 않으면
- q :=x - 1
- r이 0과 같으면 -
- 루프에서 빠져나오기
- res :=res + r
예
이해를 돕기 위해 다음 구현을 살펴보겠습니다. −
#include<bits/stdc++.h> using namespace std; int solve(vector<vector<int>>& matrix) { int n = matrix.size(); int m = matrix[0].size(); int add[n + 1][m + 1]; memset(add, 0, sizeof(add)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { add[i + 1][j + 1] += matrix[i][j]; add[i + 1][j + 1] += add[i][j + 1]; add[i + 1][j + 1] += add[i + 1][j]; add[i + 1][j + 1] -= add[i][j]; } } int res = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (!matrix[i][j]) continue; for (int k = 1; k <= (n - i); k++) { int p = 0, q = m - j; int r; while (p <= q) { int x = (p + q) / 2; int a = k * x; int cur = add[i + k][j + x] - add[i][j + x] - add[i + k][j] + add[i][j]; if (cur == a) { r = x; p = x + 1; } else q = x - 1; } if (r == 0) break; res += r; } } } return res; } int main() { vector<vector<int>> mat = {{0, 0, 1, 0}, {0, 1, 0, 0}, {0, 1, 0, 1}, {1, 1, 0, 1}}; cout<< solve(mat) <<endl; return 0; }
입력
{{0, 0, 1, 0}, {0, 1, 0, 0}, {0, 1, 0, 1}, {1, 1, 0, 1}}
출력
12