백준
[C++] 백준 2829 아름다운 행렬 [Gold3]
MINU.SHINNNN
2023. 1. 18. 18:18
풀이
정사각 행렬의 주대각선 합과 나머지 대각선 합의 차이의 최대값을 구하는 문제.
N<=400 이므로, {정사각형 크기 결정 - row결정 - col결정 - Diagonal 계산} 반복문의 경우 O(N^4) = 25,600,000,000이다.
구간합 아이디어를 적용해 Diagonal 계산 for loop를 없앤다면 O(N^3) = 64,000,000 으로 1초 제한에 걸리지 않는다.
1. 입력을 받아올 때 주대각선 구간합 벡터 main_d 와 나머지 대각선 구간합 벡터 sub_d를 업데이트 한다.
2. 이때 sub_d는 오른쪽 끝 열을 0으로 만들도록 채운다.
3. 3중 for loop로 현재 (정사각형 크기, row, col)에서 주대각선 합과 나머지 대각선 합을 구한 후 차이를 업데이트 한다.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
// freopen("2829.txt", "r", stdin);
int N, num;
cin >> N;
vector<vector<int>> sub_d(N+1, vector<int> (N+1, 0));
vector<vector<int>> main_d(N+1, vector<int> (N+1, 0));
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> num;
// Diagonal Prefix Sum
main_d[i+1][j+1] = main_d[i][j] + num;
sub_d[i+1][j] = sub_d[i][j+1] + num;
}
}
int ans = 0;
for (int area = 2; area <= N; area++) {
// 크기 2인 정사각 행렬부터 N까지 검사
for (int row = 0; row < N+1-area; row++) {
for (int col = 0; col < N+1-area; col++) {
// 대각선 구간합 가져오기
int md = main_d[row+area][col+area] - main_d[row][col];
int sd = sub_d[row+area][col] - sub_d[row][col+area];
ans = max(md - sd, ans);
}
}
}
cout << ans << "\n";
return 0;
}