티스토리 뷰
반응형
✏️ 문제 링크
https://www.acmicpc.net/problem/2573
✏️ 문제 설명
✏️ 로직
- 배열을 입력받기
- bfs로 탐색하여 나뉘어졌는지 확인
- 빙산 녹이기
- 빙산이 모두 녹았는지 확인
- 2~4의 과정을 계속 반복하기
✏️ 코드
#include<bits//stdc++.h>
using namespace std;
int arr[301][301];
int arr2[301][301];
bool visited[301][301];
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
// 0이 아닌 곳 중 하나를 시작점으로 넣어서 탐색
int bfs(int n, int m) {
queue<pair<int,int>>q;
int count=0;
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
if(arr[i][j] ==0 || visited[i][j])
continue;
q.push({ i,j });
visited[i][j]=true;
count++;
while (!q.empty()) {
int x = q.front().first;
int y = q.front().second;
q.pop();
for(int k=0;k<4;k++) {
int mx = x+dx[k];
int my = y+dy[k];
if (mx<0 || mx>=n || my<0 || my>=m)
continue;
if(arr[mx][my] == 0 || visited[mx][my])
continue;
visited[mx][my]=true;
q.push({ mx,my });
}
}
}
}
for (int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
visited[i][j]=false;
}
}
return count;
}
void copyArrToArr2(int n,int m) {
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
arr2[i][j]=arr[i][j];
}
}
}
void updateArr(int n,int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (arr[i][j]) {
if (j-1 >=0 && j-1<m ) { // 범위 안에 들어갈 때
if (arr[i][j-1] == 0 && arr[i][j]>0 && arr2[i][j-1] == 0)
arr[i][j] -= 1;
}
else { // 범위 밖에 있을 때
if ( arr[i][j]>0)
arr[i][j] -= 1;
}
if (j+1 >=0 && j+1<m) { // 범위 안에 들어갈 때
if (arr[i][j+1] == 0 && arr[i][j]>0 && arr2[i][j+1] == 0)
arr[i][j] -= 1;
}
else { // 범위 밖에 있을 때
if (arr[i][j]>0)
arr[i][j] -= 1;
}
if (i-1 >=0 && i-1<n) { // 범위 안에 들어갈 때
if (arr[i-1][j] == 0 && arr[i][j]>0 && arr2[i-1][j] == 0)
arr[i][j] -= 1;
}
else { // 범위 밖에 있을 때
if (arr[i][j]>0)
arr[i][j] -= 1;
}
if (i+1 >=0 && i+1<n) { // 범위 안에 들어갈 때
if (arr[i+1][j] == 0 && arr[i][j]>0 && arr2[i+1][j] == 0)
arr[i][j] -= 1;
}
else { // 범위 밖에 있을 때
if (arr[i][j]>0)
arr[i][j] -= 1;
}
}
}
}
}
// false면 모두녹은 것임
bool checkArr(int n,int m) {
for (int i=0;i<n;i++) {
for (int j=0;j<m;j++) {
if (arr[i][j] != 0)
return true;
}
}
return false;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
arr2[i][j]=-1;
}
}
// 입력 받기
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
cin>>arr[i][j];
}
}
int count = 0;
copyArrToArr2(n,m);
while(true) {
int result = bfs(n,m);
if(result>=2) {
cout<<count<<"\\n";
break;
}
copyArrToArr2(n,m);
updateArr(n,m);
bool check = checkArr(n,m);
if (check == false) {
if (count == 0) {
cout<<1;
}
else
cout<<0;
break;
}
count++;
}
}
✏️ 결과
어쩔 수 없이 메모리를 많이 잡아먹긴 했는데 사람들의 결과를 봤을 때 이 정도면 매우 양호한 것 같고 80ms면 준수하게 푼 것 같다. 다 풀고 사람들의 풀이를 몇 개씩 확인했는데 다른 로직은 확인하지 못하였고 로직 상 시간 초과는 발생하지 않을 것 같아 보였다.
- 배열을 입력받는 시간 O(NM)
- 빙산을 검사하는 시간 O(NM)
- 빙산을 녹이는 시간 O(NM)
- BFS 탐색 시간 O(N+M)
- 내 생각에는 최고로 걸린 시간 ⇒ 300 * 300 * k ⇒ 900000정도
✏️ 느낀 점
- 문제 자체는 어렵지 않았는데 구현 부분에서 생각보다 애를 먹었다 ⇒ 1시간 반정도 걸림
- 처음에는 아무 생각 없이 빙산을 모두 녹였는데 다음과 같은 에러사항이 있었다. 무조건 다 녹이게 되면 같은 년동안 녹은 빙산이 다른 빙산에도 영향을 끼친다는 점 ⇒ 이전 배열 값을 저장할 수 있는 배열 추가
- 빙산을 녹일 때마다 범위를 확인하고 이전 값을 저장한 배열이 0일 때만 빙산을 녹여야 한다는 점
- 마지막 조건을 보지 못했는데 땅이 분리되기 전에 모두 녹아버리면 0을 출력해야 한다는 점
- c의 조건을 만족시켰지만, 가운데 값이 0이고 나머지 갑이 모두 1인 정사각형인 경우에는 땅이 분리되기 전에 모두 녹지만 1을 출력해야 한다는 점
- bfs로 나뉘어졌는지를 확인하는 부분은 어렵지 않았다.
- 약 8~9개월만에 백준을 다시 풀었는데 확실히 속도가 떨어진 것 같다. 다시 열심히 노력해서 풀어야 할 것 같다.
반응형
'Algorithm > BOJ' 카테고리의 다른 글
[C/C++] 백준 9471번 - 피사노 주기 (0) | 2025.01.08 |
---|---|
[C/C++] 백준 2749번 - 피보나치 수 3 (0) | 2025.01.07 |
[C/C++] 백준 2579번 - 계단 오르기 (0) | 2024.05.12 |
[C/C++] 백준 16929번 - Two Dots (0) | 2024.05.05 |
[C/C++] 백준 2589번 - 보물섬 (0) | 2024.05.04 |
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- HTML5
- 알고리즘 공부
- DP
- 반복문
- C++
- 백준
- 카운팅 정렬
- 우선순위 큐
- 백준 풀이
- 세그먼트 트리
- html
- CSS
- 유클리드 호제법
- 자료구조
- C++ Stack
- 투 포인터
- 스프링 부트 crud 게시판 구현
- 이분 매칭
- 알고리즘
- js
- DFS
- java
- BFS
- Do it!
- c++ string
- 유니온 파인드
- 자바
- 스택
- 자바스크립트
- 에라토스테네스의 체
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함