[BOJ]
[BOJ] [C++] 1028 다이아몬드 광산
준제
2023. 11. 4. 16:56
https://www.acmicpc.net/problem/1028
1028번: 다이아몬드 광산
첫째 줄에 R과 C가 주어진다. R과 C는 750보다 작거나 같은 자연수이다. 둘째 줄부터 R개의 줄에는 다이아몬드 광산의 모양이 주어진다.
www.acmicpc.net
입력 내에서 가장 큰 다이아몬드 모양의 길이를 출력하는 문제이다. 문제 해결을 위해선 공통적으로, 대각선 길이에 대한 아이디어가 필요하다.

문제의 핵심은 grid[i][j]로부터 뻗어나오는 대각선의 길이를 배열에 저장하는 것이다. 이 과정에서 Dinamic Programming을 사용하고, 이후는 다양한 방법으로 접근할 수 있다.
DP_D[2][i][j], DP_U[2][i][j]를 만들었다. 각각은 연속된 1의 개수를 의미한다.
DP_D[0] = ↘ // DP_D[1] = ↙
DP_U[0] = ↖ // DP_U[1] = ↗
1. 입력을 받으며 DP_U와 DP_D를 구한다
2. 3중 반복문을 돌리면서 최대 길이를 갱신한다
// ANSWER
#include <iostream>
#include <algorithm>
using namespace std;
int grid[760][760];
int DP_D[2][760][760]; // 연속된1의개수 // 0 = ↘ // 1 = ↙
int DP_U[2][760][760]; // 연속된1의개수 // 0 = ↖ // 1 = ↗
int main(){
int R, C;
int ans = 0;
scanf("%d %d", &R, &C);
for (int i = 1 ; i <= R ; i ++){ //입력받으며 DP_U 생성
for (int j = 1 ; j <= C ; j ++){
scanf("%1d", &grid[i][j]);
if (grid[i][j] == 1) {
DP_U[0][i][j] = DP_U[0][i - 1][j - 1] + 1;
DP_U[1][i][j] = DP_U[1][i - 1][j + 1] + 1;
}
else {
DP_U[0][i][j] = 0;
DP_U[1][i][j] = 0;
}
}
}
for (int i = R ; i >= 0 ; i --){ //역순. DP_D 생성
for (int j = C ; j >= 0 ; j --){
if (grid[i][j] == 1) {
DP_D[0][i][j] = DP_D[0][i + 1][j - 1] + 1;
DP_D[1][i][j] = DP_D[1][i + 1][j + 1] + 1;
}
else {
DP_D[0][i][j] = 0;
DP_D[1][i][j] = 0;
}
}
}
for (int i = 1; i <= R; i++){
for (int j = 1; j <= C; j++){ //모든 좌표에 대해 검사
int tmp1 = min(DP_D[0][i][j], DP_D[1][i][j]);
for (int len = 1; len <= tmp1; len++) {
//해당 좌표에서 가능한 모든 길이를 알기 위해, 반복문으로 검사
int k = (len - 1) * 2;
int tmp2 = min(DP_U[0][i+k][j], DP_U[1][i+k][j]);
if (tmp2 >= len) ans = max(ans, len);
}
}
}
printf("%d", ans);
}