문제 접근
처음에는 아무 생각없이 코드 작성했는데, 지금 보니까 시간 복잡도가 O(N^2*M^2) 인 것 같다 ( 최악의 경우 cnt 가 N*M 이므로). 시간 초과 나오길래 BFS 로 다시 구현했다.
BFS 로 구현한 코드는 시간복잡도가 O(V+E) 인 것 같다. ( V : 값이 1인 정점의 개수, E : 값이 1인 정점에서 값이 0인 정점으로 향하는 간선의 개수 )
시간 복잡도를 계산하는 것에 조금 더 익숙해질 필요가 있는 것 같다.
문제 코드 ( 시간 초과 )
#include <iostream>
#include <algorithm>
using namespace std;
// cnt = 0의 개수
// 모든 0이 지워져야되는거니 루프마다 0의 개수를 세기보다는 cnt 를 감소하도록 구현했다.
int M,N,cnt=0,ans=0;
int box[1002][1002];
bool visited[1002][1002];
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
// 확인용 box 출력 함수
void print()
{
for(int i=0; i<=N+1; ++i)
{
for(int j=0; j<=M+1; ++j)
{
cout.fill(' ');
cout.width(2);
cout<<box[j][i]<<' ';
}
cout<<'\n';
}
cout<<"=====================\n";
}
int simulate()
{
// 0 주변이 모두 -1 이라면 1이 접근할 수 없기에 -1 이 출력되어야 한다.
for(int i=1; i<=N; ++i)
for(int j=1; j<=M; ++j)
if(box[j][i]==0 && box[j+1][i] + box[j][i+1] + box[j-1][i] + box[j][i-1] == -4)
return -1;
// 0 의 개수가 1개 이상이라면 실행
while(cnt>0)
{
// 이 코드에서 visited 는 한 번 실행할 때마다 방문 여부 확인하는 것이기에 초기화 함.
fill(&visited[0][0],&visited[1001][1001],false);
for(int i=1; i<=N; ++i)
for(int j=1; j<=M; ++j)
// 바뀐 1의 좌표를 확인하지 않도록 조건 걸음.
if(!visited[j][i] && box[j][i]==1)
for(int k=0; k<4; ++k)
if(!visited[j+dx[k]][i+dy[k]] && box[j+dx[k]][i+dy[k]]==0)
{
// BFS 로 한 번 확인할 때 1로 바꾼 부분까지 또 확인해서 바뀐 좌표를 true 로 설정함.
visited[j+dx[k]][i+dy[k]] = true;
box[j+dx[k]][i+dy[k]]=1;
--cnt;
}
//print();
++ans;
}
return ans;
}
int main(void)
{
fill(&box[0][0], &box[1001][1001],-1);
cin>>M>>N;
for(int i=1; i<=N; ++i)
for(int j=1; j<=M; ++j)
{
cin>>box[j][i];
if(box[j][i]==0)
++cnt;
}
//print();
cout<<simulate()<<'\n';
}
실행 결과 ( 시간 초과 )
문제 코드 ( 맞았습니다! )
#include <iostream>
#include <queue>
using namespace std;
int main(void)
{
int M,N,cnt=0,ans=0, x, y;
int box[1002][1002];
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
queue<vector<pair<int,int>>> q;
// queue 에 넣을 좌표들을 저장한 vector
vector<pair<int,int>> coor;
vector<pair<int,int>> temp;
fill(&box[0][0], &box[1001][1001],-1);
cin>>M>>N;
for(int i=1; i<=N; ++i)
for(int j=1; j<=M; ++j)
{
cin>>box[j][i];
if(box[j][i]==0)
++cnt;
else if(box[j][i]==1)
coor.push_back(make_pair(j,i));
}
q.push(coor);
while(!q.empty())
{
coor.clear();
coor = q.front();
q.pop();
for(int i=0; i<coor.size(); ++i)
for(int j=0; j<4; ++j)
{
x = coor[i].first;
y = coor[i].second;
if(box[x+dx[j]][y+dy[j]]==0)
{
box[x+dx[j]][y+dy[j]] = 1;
temp.push_back(make_pair(x+dx[j], y+dy[j]));
--cnt;
}
}
// temp.empty() 를 확인하지 않으면 빈 vector 가 queue 로 넘어가 무한 루프 걸린다.
if(!temp.empty())
q.push(temp);
temp.clear();
++ans;
}
// 바꿀 수 있는 0을 전부 바꿨는데도 0이 남아있으면 모두 익히지 못하는 상황이므로 -1 출력.
if(cnt)
cout<<"-1\n";
// ans-1 인 이유는 마지막에 바꿀 수 있는 0을 전부 바꿔서 temp 가 비었을 때도 ++ans 되기 때문이다.
else
cout<<ans-1<<'\n';
}
'개발 > 알고리즘' 카테고리의 다른 글
백준 18870번 : 좌표 압축 (0) | 2020.08.16 |
---|---|
백준 11724번 : 연결 요소의 개수 (0) | 2020.08.16 |
백준 1629번 : 곱셈 (0) | 2020.08.14 |
백준 1931번 : 회의실 배정 (0) | 2020.08.14 |
백준 1697번 : 숨바꼭질 (0) | 2020.08.14 |