백준
[C++] 백준 2667번 단지 붙이기 (Silver 1)
MINU.SHINNNN
2023. 1. 15. 18:19
풀이
DFS 접근 법을 통해 해결하면 된다. 전형적인 DFS 문제라고 한다...
1. 깊이우선 탐색을 통해 처음 1을 발견하면, 모든 연결된 1을 방문하면서 넓이를 +1 해주면 된다.
2. 처음 발견한 곳은 visited[row][col] 어레이를 통해 확인하면 된다.
3. 재귀 방식 dfs(int r, int c)과 스택 방식 dfs_stk(int r, int c) 모두 테스트 해보았다.
리뷰
그래프 문제 풀려고 선택한 문제인데, 아무 생각 없이 DP로 접근했다가 후퇴한 문제다...
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <stack>
using namespace std;
int map[25][25];
int visited[25][25];
vector<int> cntVec;
//위 오 아 왼
int dr[4] = {-1,0,1,0};
int dc[4] = {0,1,0,-1};
int N;
int cnt;
void dfs(int r, int c){
for(int i = 0; i<4; i++){
int nr = r + dr[i];
int nc = c + dc[i];
if(nr>=N || nr<0 || nc>=N || nc<0) continue;
if(visited[nr][nc]==0 && map[nr][nc]==1){ //방문 안했고 집이 있으면
visited[nr][nc] = 1; //방문했다고 표시하고
cnt+=1; //집 개수 세기
dfs(nr,nc);
}
}
}
void dfs_stk(int r, int c)
{
stack<pair<int, int>> stk;
stk.push({r, c});
while (!stk.empty()) {
pair<int, int> v = stk.top();
stk.pop();
if (visited[v.first][v.second]) continue;
visited[v.first][v.second] = 1;
cnt+=1;
for (int i = 0; i < 4; i++) {
int nr = v.first + dr[i];
int nc = v.second + dc[i];
if(nr>=N || nr<0 || nc>=N || nc<0) continue;
if(visited[nr][nc]==0 && map[nr][nc]==1){ //방문 안했고 집이 있으면
stk.push({nr, nc});
}
}
}
}
int main(){
int res=0;
freopen("2667.txt", "r", stdin);
cin >> N;
string str;
for(int i = 0; i<N; i++){
cin >> str;
for(int j = 0; j<str.length(); j++){ //입력 주의
visited[i][j] = 0;
if(str[j] == '1'){
map[i][j] = 1;
}
else map[i][j] = 0;
}
}
for(int i = 0; i<N; i++){
for(int j = 0; j<N; j++){
if(map[i][j]==1 && visited[i][j]==0){
// visited[i][j] = 1;
cnt = 0; //처음은 시작점 포함하므로 1로 초기화
// dfs(i,j);
dfs_stk(i,j);
cntVec.push_back(cnt);
res++; //단지 그룹 1개 탐색 끝남
}
}
}
sort(cntVec.begin(), cntVec.end());
cout << res << "\n";
for(int i = 0; i<cntVec.size(); i++){
cout << cntVec[i] << "\n";
}
return 0;
}