작성
·
308
·
수정됨
0
안녕하세요 강사님.
강사님 1주차는 잠시 건너뛰고
2주차 시작하고 있는데
2주차 개념강의를 듣고 문제를 풀고 있습니다.
이미 제가 학교에서 배웠던 개념을 의사 코드로 잘 표현하신 개념강의가 확실히 이해가 잘 되고 응용도 잘 되는 것 같습니다.
잡소리가 길었고 질문 드립니다.
/*
답 : http://boj.kr/c6ad22b6eb274064b90a2fb2c3509961
*/
#include <bits/stdc++.h>
using namespace std;
int N;
int m[104][104];
bool visited[104][104];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
void dfs(pair<int, int> node, int height)
{
visited[node.first][node.second] = true;
for(int i = 0; i < 4; i++)
{
int nx = node.first + dx[i];
int ny = node.second + dy[i];
if(nx < 0 || nx >= N || ny < 0 || ny >= N)
continue;
if(m[nx][ny] > height && !visited[nx][ny])
dfs({nx, ny}, height);
}
}
int main(void)
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int max_height = 0;
cin >> N;
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
{
cin >> m[i][j];
max_height = (max_height < m[i][j]) ? m[i][j] : max_height;
}
// 모든 영역의 값이 1일 경우 반복문이 돌지 않는다.
// 또한, 아무 지역도 물이 잠기지 않을 수 있으므로
// 최솟값은 1로 지정해야한다.
int answer = 1;
for(int tc = 1; tc < max_height; tc++)
{
// N * N 이 아닌
// 104 * 104 으로 해야 정상적으로 된다.
// 이유는 모르겠다.
fill(&visited[0][0], &visited[0][0] + 104 * 104, 0);
int count = 0;
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
if(m[i][j] > tc && !visited[i][j])
{
dfs({i, j}, tc);
count++;
}
answer = (answer < count) ? count : answer;
}
cout << answer << '\n';
return 0;
}
핵심 로직은 다 짜고 이해도 됐는데 저
fill(&visited[0][0], &visited[0][0] + 104 * 104, 0);
이 부분에서 fill 함수의 두 번째 인자가
&visited[0][0] + N * N 을 하면 안되고
&visited[0][0] + 104 * 104 이여야 정상 작동하는 것인가요?
예제 1을 기준으로
visited 2차원 배열을 N * N 만큼 출력 해봤는데
N * N 의 경우 해당 범위만큼
0 으로 채워지지 않았습니다.
이유가 궁금합니다.
답변 1
1
안녕하세요 123님ㅎㅎ
먼저 칭찬감사합니다. ㅎㅎ 더욱 노력하겠습니다.
123님이 문의하신 fill에 관한 내용은 교안내 설명이 되어있으며 다음과 같은 부분을 참고하시면 됩니다.
감사합니다.
음.. 사이트나 키워드가 아니라 제가 알려드릴게요.
예를 들어서
1 2 3
4 5 6
이런 배열이 있다고 합시다.
그러면 어떻게 초기화가 되냐면
1, 2, 3, 4, 5, 6 이런식으로 초기화가 됩니다. 이는 주솟값부터 순차적으로 초기화가 되기 때문에 그렇습니다.
fill 함수 내부의 코드를 볼까요?
template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
while (first != last) {
*first = val;
++first;
}
}
이런식으로 이터레이터를 ++ 해가면서 순차적으로 주솟값을 증가시키면서 해당 val로 초기화를 하고 있습니다.
#include<bits/stdc++.h>
using namespace std;
int a[2][3] =
{
{1, 2, 3},
{4, 5, 6}
};
int main(){
for(int i = 0; i < 2; i++){
for(int j = 0; j < 3; j++){
cout << &a[i][j] << "\n";
}
}
return 0;
}
/*
0x472010
0x472014
0x472018
0x47201c
0x472020
0x472024
*/
앞의 코드처럼 주솟값은 순차적으로 형성되어있는 것을 볼 수 있구요.
감사합니다.
아... 이제 이해를 했습니다.
정의를 보고 다시 예제를 입력하니 바로 이해가 되네요.
만약 배열의 크기가 104 * 104 이고 N = 5 라면 코드 속 로직 부분부분에 operator[] 연산을 통해서 정확히 특정 부분에 대한 값을 바꾸지만
fill 템플릿 함수 정의에 의해서 주솟값의 산술연산으로 해당 last 이터레이터까지 순회하므로
접근 방식 자체가 달랐던거였네요.
결국 정리하자면 해당 last 이터레이터까지 주솟값을 증가시키며 비교
vs
operator[] 를 통한 요소 접근
의 차이로 인한 오해였습니다.
즉,
operator[] 로 접근
0 ~ 4
104 ~ 107
108 ~ 111
112 ~ 115
fiil은 0 ~ 104, 105, ..., last iterator 접근
다소 지엽적인 문제였는데 친절히 알려주셔서 감사합니다.
이렇게 저를 보면 강사님도 여간 고생하는게 아니시군요;
답변 감사합니다.
그 부분을 참고해서 봤는데
라고 하셨는데
이게 정확하게 무슨 의미인지 이해가 되지 않습니다.
참고할 수 있는 사이트나 키워드를 알려주실 수 있나요?
시간이 되시면 원리를 구체적으로 알려주시면 더 좋을 것 같습니다.