CS/Algorithm
[BOJ][C++] 15683 감시
별토끼.
2019. 1. 17. 09:37
반응형
[BOJ][C++] 15683 감시
문제
https://www.acmicpc.net/problem/15683
풀이
이 문제에서는 감시 카메라마다의 모든 방향 경우를 정한 뒤 감시 영역을 체크하는 방식으로 풀었습니다.
구조체를 활용하여 0과 6이 아닌 CCTV의 수를 입력받을 때 마다 구조체에 정보를 담아 vector에 넣어주었습니다.
그 후 이 벡터를 방향 정하는 알고리즘으로 넘겨줍니다.
벡터 내의 CCTV를 모두 돌아주면서 방향을 정해줍니다. 이 때, 재귀를 활용하여 모든 경우의 수를 따질 수 있도록 설계합니다. cnt 변수로 몇 번째 CCTV의 방향을 체크중인지 확인합니다.
모든 CCTV의 수와 cnt가 일치하면 방향에 따른 감시 영역을 체크하는 함수로 넘어갑니다.
감시 영역을 체크한 뒤 사각지대의 min값을 도출해 냅니다.
코드
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int N, M, res = 987654321;
int map[8][8];
int copyMap[8][8];
int dx[] = { 0,-1,0,1 };
int dy[] = { 1,0,-1,0 };
int cctvNum;
void copy(int(*map1)[8], int(*map2)[8]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
map1[i][j] = map2[i][j];
}
}
}
struct CCTV {
int x;
int y;
int dir; //방향
int camNum; //카메라 번호
};
void Right(int x, int y) {
for (int i = y; i < M; i++) {
if (copyMap[x][i] == 6) break;
if (copyMap[x][i] == 0) copyMap[x][i] = -1;
}
}
void Down(int x, int y) {
for (int i = x; i < N; i++) {
if (copyMap[i][y] == 6) break;
if (copyMap[i][y] == 0) copyMap[i][y] = -1;
}
}
void Left(int x, int y) {
for (int i = y; i >= 0; i--) {
if (copyMap[x][i] == 6) break;
if (copyMap[x][i] == 0) copyMap[x][i] = -1;
}
}
void Top(int x, int y) {
for (int i = x; i >= 0; i--) {
if (copyMap[i][y] == 6) break;
if (copyMap[i][y] == 0) copyMap[i][y] = -1;
}
}
void CountSavezone(vector<CCTV> cctv) {
copy(copyMap, map);
for (int i = 0; i < cctv.size(); i++) {
if (cctv[i].camNum == 1) {
if (cctv[i].dir == 0) { //오른쪽
Right(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 1) { //아래
Down(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 2) { //왼쪽
Left(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 3) { //위쪽
Top(cctv[i].x, cctv[i].y);
}
}
else if (cctv[i].camNum == 2) {
if (cctv[i].dir == 0 || cctv[i].dir == 2) {
Right(cctv[i].x, cctv[i].y);
Left(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 1 || cctv[i].dir == 3) {
Down(cctv[i].x, cctv[i].y);
Top(cctv[i].x, cctv[i].y);
}
}
else if (cctv[i].camNum == 3) {
if (cctv[i].dir == 0) {
Right(cctv[i].x, cctv[i].y);
Down(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 1) {
Down(cctv[i].x, cctv[i].y);
Left(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 2) {
Left(cctv[i].x, cctv[i].y);
Top(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 3) {
Top(cctv[i].x, cctv[i].y);
Right(cctv[i].x, cctv[i].y);
}
}
else if (cctv[i].camNum == 4) {
if (cctv[i].dir == 0) {
Left(cctv[i].x, cctv[i].y);
Top(cctv[i].x, cctv[i].y);
Right(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 1) {
Top(cctv[i].x, cctv[i].y);
Right(cctv[i].x, cctv[i].y);
Down(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir == 2) {
Right(cctv[i].x, cctv[i].y);
Down(cctv[i].x, cctv[i].y);
Left(cctv[i].x, cctv[i].y);
}
else if (cctv[i].dir = 3) {
Down(cctv[i].x, cctv[i].y);
Left(cctv[i].x, cctv[i].y);
Top(cctv[i].x, cctv[i].y);
}
}
else if (cctv[i].camNum == 5) {
Right(cctv[i].x, cctv[i].y);
Down(cctv[i].x, cctv[i].y);
Left(cctv[i].x, cctv[i].y);
Top(cctv[i].x, cctv[i].y);
}
}
int cnt = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (copyMap[i][j] == 0) cnt++;
}
}
res = min(res, cnt);
}
void FixDirection(int index, vector<CCTV> cctv) {
if (index == cctvNum) {
CountSavezone(cctv);
return;
}
cctv[index].dir = 0; //오른쪽
FixDirection(index + 1, cctv);
cctv[index].dir = 1; //아래
FixDirection(index + 1, cctv);
cctv[index].dir = 2; //왼쪽
FixDirection(index + 1, cctv);
cctv[index].dir = 3; //위쪽
FixDirection(index + 1, cctv);
}
int main() {
scanf("%d %d", &N, &M);
vector<CCTV> cctv;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
scanf("%d", &map[i][j]);
if (map[i][j] != 0 && map[i][j] != 6) {
cctv.push_back({ i,j,0,map[i][j] });
}
}
}
//cctv의 수
cctvNum = (int)cctv.size();
FixDirection(0, cctv);
printf("%d\n", res);
}
반응형