백준 16236 아기상어
아기 상어
아기 상어가 먹이를 먹으면 크기가 커지는데, 상어가 물고기를 잡아먹을 수 있는 시간을 출력하는 문제.
문제분석
첫째, 먹을 수 있는 가장 가까운 물고기를 먹으러 간다.
현재 아기 상어의 위치에서 bfs 탐색을 통해 먹을 수 있는 최단거리 물고기를 구한다.
둘째, 물고기가 1마리 이상이라면, 가장 위 -> 가장 왼쪽에 있는 물고기를 구한다.
bfs 탐색의 특징중 최단거리가 여러개면 그때마다 벡터에 값을 추가할 수 있으므로 정답 조건을 만족할 때마다 정답에 추가한 뒤에, bfs함수 마지막에 정답 배열(vector<tuple<정답,행,열»)을 정렬하면, 정답, 행, 열 순으로 정렬될 것이다.
셋째, 상어는 자신의 크기와 같은 수의 물고기를 먹을 때 마다 크기가 1 증가하므로 크기를 매번 바꾸어준다
bfs함수가 한번 끝날 때 마다, 정답배열이 비어있으면 -1을 return해주고, -1이 아니면 정답이 존재하는 것이므로, 상어가 한번 먹었다고 처리해주고, 먹은 물고기의 개수가 상어의 크기가 같으면 상어의 크기가 한번 증가한다고 처리해준다.
go함수를 n^2번 실행한 이유는 물고기가 모든 칸에 있다고 가정했기 때문이다.
(상어의 처음 위치를 빼면 n^2-1).
오타나 질문, 지적 환영입니다.
소스
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int ma[100][100];
int x_index[4]={-1,0,0,1};
int y_index[4]={0,-1,1,0};
int n;
int shark=2;
int s_exp=0;
tuple<int,int,int> go(int x,int y){ //아기상어의 위치
int ans=0;
int d[21][21]={0};
queue<tuple<int,int,int>> q;
q.push(make_tuple(0,x,y));
vector<tuple<int,int,int>> ansv;
while(!q.empty()){
tie(d[x][y],x,y)=q.front();q.pop();
int nx,ny;
for(int i=0;i<4;i++){
nx=x+x_index[i];
ny=y+y_index[i];
if(nx<0 || ny<0 || nx>=n || ny>=n)
continue;
if(ma[nx][ny]>shark || d[nx][ny]>0)
continue;
if(ma[nx][ny]==0 || ma[nx][ny]==shark){
d[nx][ny]=d[x][y]+1;
q.push(make_tuple(d[nx][ny],nx,ny));
}
if(ma[nx][ny]<shark && ma[nx][ny]!=0){
ans=d[x][y]+1;
ansv.push_back(make_tuple(ans,nx,ny));
}
}
}
if(ansv.empty()){
return make_tuple(-1,-1,-1);
}
sort(ansv.begin(), ansv.end());
return ansv[0];
}
int main(){
cin>>n;
int x,y;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>ma[i][j];
if(ma[i][j]==9){
x=i;
y=j;
ma[i][j]=0;
}
}
}
int ans=0;
int tmp=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
tie(tmp,x,y)=go(x,y);
if(x==-1 || y==-1 || tmp==-1)
break;
ma[x][y]=0;
s_exp++;
if(s_exp==shark)
{
shark++;
s_exp=0;
}
ans+=tmp;
}
}
cout<<ans<<'\n';
}
댓글남기기