알고리즘/백준

15683 감시

https://www.acmicpc.net/problem/15683

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감시할 수 있는 방법은 다음과 같다. 1번 CCTV는 한 쪽 방향만 감시할 수 있다. 2번과 3번은 두 방향을 감시할 수 있는데, 2번은 감시하는 방향이 서로 반대방향이어야 하고, 3번은 직각 방향이어야 한다. 4번은 세 방향, 5번은 네 방향을 감시할

www.acmicpc.net

유형: 시뮬레이션

1. 한 방향만 보는 함수를 생성 see함수 생성

2. cctv 갯수만큼 재귀함수를 돌린다

3. cctv타입 마다 볼 수 있는 방법이 정해져 있음

int type_size[5] = {4,2,4,4,1};

예를 들면 타입0은 {동}{서}{남}{북} 전부 보는게 가능

타입1은 서로 {동서}, {남북} 자가지 경우의수 가능

이 처럼 위에 식대로 미리 크기를 정해 놓는다.

 

얼핏보면 dfs와 비슷해 보이지만 재귀를 빠져나갔을 경우 

다시 backup한 데이터로 map배열을 초기화 시켜줘야 한다.

이 점이 dfs와 다른 점이다.

/*
	사각지대 최소크기
	재귀사용
	큐 사용
	struct
		y,x,type
	main
		입력
			cctv.push
	sol
		if cnt==cctv갯수
			완전탐색
				ans <- -1갯수 최대값
			return

		for type별 경우의수
			backup = map
			1유형
				see(d, info)
			2유형
				see(d, info )
				see(d+2, info )
			...

			map = backup

		
	see
		d=d%4
		if d==0
			for
				if 벽 break
				map <- -1
*/
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
struct INFO {
	int y, x, ty;
};
int N, M;
int map[8][8];
INFO info[8];
int tv_num;
int dx[4] = { 0,1,0,-1 };
int dy[4] = { -1,0,1,0 };
int type_size[5] = {4,2,4,4,1};
int ans = 64;
void see(int d,int index) 
{
	int dir = d % 4;
	if (dir == 0)//북
	{
		for (int i = info[index].y; i >= 0; i--)
		{
			if (map[i][info[index].x] == 6 ) break;
			else if(map[i][info[index].x]==0)
				map[i][info[index].x] = -1;
		}
	}
	else if (dir == 1)//동
	{
		for (int i = info[index].x; i <M; i++)
		{
			if (map[info[index].y][i] == 6) break;
			else if (map[info[index].y][i] == 0)
				map[info[index].y][i] = -1;
		}
	}
	else if (dir == 2)//남
	{
		for (int i = info[index].y; i<N; i++)
		{
			if (map[i][info[index].x] == 6) break;
			else if (map[i][info[index].x] == 0)
				map[i][info[index].x] = -1;
		}
	}
	else if (dir == 3)//서
	{
		for (int i = info[index].x; i >=0; i--)
		{
			if (map[info[index].y][i] == 6) break;
			else if (map[info[index].y][i] == 0)
				map[info[index].y][i] = -1;
		}
	}
}
void sol(int index)
{
	if (index == tv_num)
	{
		int ret = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				if (map[i][j] == 0) ret++;
			}
		}
		ans = min(ans, ret);
		return;
	}
	for (int i = 0; i < type_size[info[index].ty];i++)
	{
		int backup[8][8];
		memcpy(backup, map, sizeof(map));
		if (info[index].ty == 0)
		{
			see(i,index);
		}
		else if (info[index].ty == 1)
		{
			see(i, index);
			see(i+2, index);
		}
		else if (info[index].ty == 2)
		{
			see(i, index);
			see(i+1, index);
		}
		else if (info[index].ty == 3)
		{
			see(i, index);
			see(i+1, index);
			see(i+2, index);
		}
		else if (info[index].ty == 4)
		{
			see(i, index);
			see(i+1, index);
			see(i+2, index);
			see(i+3, index);
		}
		sol(index + 1);
		memcpy(map, backup, sizeof(map));
	}
}
int main() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> map[i][j];
			if (map[i][j] != 0 && map[i][j] != 6) {
				info[tv_num].y = i;
				info[tv_num].x = j;
				info[tv_num].ty = map[i][j]-1;
				tv_num++;
			}
		}
	}
	sol(0);
	cout << ans;
}

'알고리즘 > 백준' 카테고리의 다른 글

백준 16234 인구 이동  (0) 2020.03.13
백준 15686 치킨 배달  (0) 2020.03.13
백준 15685 드래곤 커브  (0) 2020.03.13
15684 사다리 조작  (0) 2020.03.13
14891번 톱니바퀴  (0) 2020.03.12