일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 포스코 ai 교육
- 컴퓨팅사고
- sort
- 삼성코테
- MCU 딥러닝
- TensorFlow Lite
- 자료구조
- bfs문제
- 알고리즘
- tflite
- 임베디드 딥러닝
- 영상처리
- 초소형머신러닝
- dfs문제
- 코딩테스트
- 딥러닝
- 포스코 교육
- DP
- dfs
- 삼성코딩테스트
- tinyml
- 코테
- 다이나믹프로그래밍
- 삼성역량테스트
- 코테 문제
- BFS
- DP문제
- 그리디
- 삼성역테
- 포스코 AI교육
- Today
- Total
코딩뚠뚠
[삼성역량테스트] 15683 감시 본문
풀이일시 : 2020-10-17
문제 :
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감시할 수 있는 방법은 다음과 같다.
1번 CCTV는 한 쪽 방향만 감시할 수 있다. 2번과 3번은 두 방향을 감시할 수 있는데, 2번은 감시하는 방향이 서로 반대방향이어야 하고, 3번은 직각 방향이어야 한다. 4번은 세 방향, 5번은 네 방향을 감시할 수 있다.
CCTV는 감시할 수 있는 방향에 있는 칸 전체를 감시할 수 있다. 사무실에는 벽이 있는데, CCTV는 벽을 통과할 수 없다. CCTV가 감시할 수 없는 영역은 사각지대라고 한다.
CCTV는 회전시킬 수 있는데, 회전은 항상 90도 방향으로 해야 하며, 감시하려고 하는 방향이 가로 또는 세로 방향이어야 한다.
지도에서 0은 빈 칸, 6은 벽, 1~5는 CCTV의 번호이다. 위의 예시에서 1번의 방향에 따라 감시할 수 있는 영역을 '#'로 나타내면 아래와 같다.
CCTV는 벽을 통과할 수 없기 때문에, 1번이 → 방향을 감시하고 있을 때는 6의 오른쪽에 있는 벽을 감시할 수 없다.
위의 예시에서 감시할 수 있는 방향을 알아보면 아래와 같다.
CCTV는 CCTV를 통과할 수 있다. 아래 예시를 보자.
위와 같은 경우에 2의 방향이 ↕ 3의 방향이 ←와 ↓인 경우 감시받는 영역은 다음과 같다.
사무실의 크기와 상태, 그리고 CCTV의 정보가 주어졌을 때, CCTV의 방향을 적절히 정해서, 사각 지대의 최소 크기를 구하는 프로그램을 작성하시오.
입력 :
첫째 줄에 사무실의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 8)
둘째 줄부터 N개의 줄에는 사무실 각 칸의 정보가 주어진다. 0은 빈 칸, 6은 벽, 1~5는 CCTV를 나타내고, 문제에서 설명한 CCTV의 종류이다.
CCTV의 최대 개수는 8개를 넘지 않는다.
ex)
4 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 6 0
0 0 0 0 0 0
출력 :
첫째 줄에 사각 지대의 최소 크기를 출력한다.
ex)
20
풀이 :
회전의 모든 경우를 탐색해주는 BF를 이용한다.
1번 cctv : 4가지 경우의 수
2번 cctv : 2가지 경우의 수
3번 cctv : 4가지 경우의 수
4번 cctv : 4가지 경우의 수
5번 cctv : 1가지 경우의 수
#include <iostream>
#include <vector>
#define MAX 8
#define INF 987654321
using namespace std;
int map[MAX][MAX];
vector<int> cctv;
vector<pair<int, int>> cctvLocation;
int N, M;
int ans = INF;
void MapCopy(int(*a)[MAX], int(*b)[MAX]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
a[i][j] = b[i][j];
}
}
}
void spread(int dir, int x, int y) {
//상
if (dir == 0) {
int ny = y - 1;
if (ny < 0) return;
if (map[ny][x] == 6) return;
map[ny][x] = 9;
spread(0, x, ny);
}
//우
else if (dir == 1) {
int nx = x + 1;
if (nx > M - 1) return;
if (map[y][nx] == 6) return;
map[y][nx] = 9;
spread(1, nx, y);
}
//하
else if (dir == 2) {
int ny = y + 1;
if (ny > N - 1) return;
if (map[ny][x] == 6) return;
map[ny][x] = 9;
spread(2, x, ny);
}
//좌
else {
int nx = x - 1;
if (nx < 0) return;
if (map[y][nx] == 6) return;
map[y][nx] = 9;
spread(3, nx, y);
}
}
void check() {
int cnt = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (map[i][j] == 0) {
cnt += 1;
}
}
}
if (cnt < ans)
ans = cnt;
}
void dfs(int cnt) {
if (cnt > (int)cctv.size() - 1) { //만약 cnt가 cctv갯수를 다 탐색했다면
//사각지대 검사
check();
return;
}
int kind = cctv[cnt]; //몇번 cctv인가
int x = cctvLocation[cnt].first; //cctv 좌표
int y = cctvLocation[cnt].second; //cctv 좌표
int temp[MAX][MAX];
//1번 cctv는 4방향
if (kind == 1) {
for (int i = 0; i < 4; i++) {
MapCopy(temp, map); //map을 temp에 복사
spread(i, x, y); //뻗어나가는 방향
dfs(cnt + 1); //cctv 배열에있는 그다음 cctv를 찾아서 dfs
MapCopy(map, temp); //다시 map으로 돌려놓기
}
}
//2번 cctv는 2방향
else if (kind == 2) {
for (int i = 0; i < 2; i++) {
MapCopy(temp, map);
spread(i, x, y);
spread(i + 2, x, y);
dfs(cnt + 1);
MapCopy(map, temp);
}
}
//3번 cctv는 4방향
else if (kind == 3) {
for (int i = 0; i < 4; i++) {
MapCopy(temp, map);
spread(i, x, y);
spread((i + 1) % 4, x, y);
dfs(cnt + 1);
MapCopy(map, temp);
}
}
//4번 cctv는 4방향
else if (kind == 4) {
for (int i = 0; i < 4; i++) {
MapCopy(temp, map);
spread(i, x, y);
spread((i + 1) % 4, x, y);
spread((i + 2) % 4, x, y);
dfs(cnt + 1);
MapCopy(map, temp);
}
}
//5번 cctv는 방향 변경x
else {
MapCopy(temp, map);
for (int i = 0; i < 4; i++) {
spread(i, x, y);
}
dfs(cnt + 1);
MapCopy(map, temp);
}
}
int main() {
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
int temp;
cin >> temp;
map[i][j] = temp;
if (temp != 0 && temp != 6) { //입력된 temp가 벽X 빈칸X cctv이면
cctv.push_back(temp); //cctv[]
cctvLocation.push_back(make_pair(j, i)); //cctv의 위치도 저장
}
}
}
//map 입력완료 후
dfs(0); //dfs(cnt=0)으로 시작
cout << ans << endl;
return 0;
}
'알고리즘 문제풀이 > 삼성역량테스트' 카테고리의 다른 글
[삼성역량테스트] 20055 컨베이어 벨트 위의 로봇 (0) | 2021.01.18 |
---|---|
[삼성역량테스트] 20056 마법사 상어와 파이어볼 (0) | 2021.01.17 |
[삼성역량테스트] 20057 마법사 상어와 토네이도 (0) | 2021.01.12 |
[삼성역량테스트] 14499 주사위 굴리기 (0) | 2021.01.03 |
[삼성역량테스트] 14503 로봇청소기 (0) | 2021.01.03 |