문제
체감 난이도(1~5) : 2.5
풀이
완전 탐색 문제. 삼성 18년도 상반기 ds 기출문제라고 한다. 입력의 크기, 맵의 크기도 작아서 보자마자 완전탐색인걸 깨닫는 문제. 그러나 구현하기가 까다롭다. 삼성문제들은 다 생각하긴 쉬운데 구현을 마구 꼬아놓은 느낌. 내가 구현한 방식은 이러하다. 첫째, CCTV가 나올때마다 vector에 저장한다. 둘째, 저장한 CCTV의 상,하,좌,우 4가지 경우로 모든 조합을 다 만든다. 셋째, 각 조합을 시뮬레이션하듯 다 만들어서 사각지대(0) 의 갯수를 센다.
int dy[8] = {1,0,-1,0,1,0,-1,0};// 상하좌우,상하좌우 공간 2배 써서 처리하기 쉽게 했다.
int dx[8] = {0,1,0,-1,0,1,0,-1};
void fill(int y,int x,int direction){
// 좌표를 받아서 direction 방향으로 감시구역을 채워나간다
while( (0<= y && y < n) && (0<=x && x < m) ){
if(arr[y][x] == 6)
break;
else
tmp[y][x] = -1;
y += dy[direction];
x += dx[direction];
}
return ;
}
int simul(){
init();
int ret = 0;
for(int i =0;i<v.size();i++)
{
int val,y,x;
y = v[i].first;
x = v[i].second;
val = arr[y][x];
switch (val){
case 1:
fill(y,x,dir[i]);
break;
case 2:
fill(y,x,dir[i]);
fill(y,x,dir[i]-2);
break;
case 3:
fill(y,x,dir[i]);
fill(y,x,dir[i]-1);
break;
case 4:
fill(y,x,dir[i]);
fill(y,x,dir[i]-1);
fill(y,x,dir[i]-2);
break;
case 5:
fill(y,x,dir[i]);
fill(y,x,dir[i]-1);
fill(y,x,dir[i]-2);
fill(y,x,dir[i]-3);
break;
}
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(tmp[i][j] ==0) ret++;
return ret;
}
void solve(int idx){
if(idx == v.size()) {
ans = min(ans,simul());
return;
}
for(int i =4;i<8;i++)
{
dir[idx] = i; // fill 함수에서 -1,-2,-3 으로 방향 판단하므로 공간 2배 주고난 후,
// 인덱스 4~7 까지 할당.
solve(idx+1);
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",&arr[i][j]);
if(arr[i][j] != 6 && arr[i][j] != 0)
v.push_back(make_pair(i,j));
}
solve(0);
printf("%d\n",ans);
return 0;
}
배운 점
- 상하좌우 방향 배열을 공간 복잡도 2배 준거 나름 아이디어 센스있었던듯!
- 다른 방법으로 하자면 (idx+1/2/3) % 4 등의 방법으로 구현한 코드도 있었다. 이 또한 좋은듯.
- 완전탐색 구현연습 많이하자.. 푸는 시간 좀 줄이자.
Comments