문제 : https://www.acmicpc.net/problem/15683
[ 알고리즘풀이 ]
CCTV는 최대 8개가 존재하고, 모든 종류의 CCTV가 가질 수 있는 경우의 수가 최대 4가지 이므로, 백트래킹을 이용해 모든 경우의 수에 대해서 조사를 해도 시간 초과 문제에 걸리지 않는다.
1. 백트래킹을 이용해 CCTV 마다 상태를 정해준다.
2. CCTV마다 상태가 정해졌다면, map을 tempMap에 복사한다. 그 후, CCTV의 종류와 상태에 따라서 CCTV가 감시하고 있는 방향들을 tempMap에서 check 해준다.
3. tempMap에 check해주는 과정이 마무리되면, 사각지대를 count 해 답을 갱신한다.
4. 2 ~ 3 과정을 반복한다.
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int N, M, C = 0, map[8][8], ans = 987654321;
vector<pair<pair<int, int>,int>> v;
vector<int> dir;
int getArea(int tempMap[8][8]) {
int count = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
if (tempMap[i][j] == 0)
count++;
return count;
}
void up(int x, int y, int tempMap[8][8]) {
for (int i = x - 1; i >= 0; i--) {
if (tempMap[i][y] == 0)
tempMap[i][y] = 9;
else if (tempMap[i][y] == 6)
break;
}
return;
}
void right(int x, int y, int tempMap[8][8]) {
for (int j = y + 1; j < M; j++) {
if (tempMap[x][j] == 0)
tempMap[x][j] = 9;
else if (tempMap[x][j] == 6)
break;
}
return;
}
void left(int x, int y, int tempMap[8][8]) {
for (int j = y - 1; j >= 0; j--) {
if (tempMap[x][j] == 0)
tempMap[x][j] = 9;
else if (tempMap[x][j] == 6)
break;
}
return;
}
void down(int x, int y, int tempMap[8][8]) {
for (int i = x + 1; i < N; i++){
if (tempMap[i][y] == 0)
tempMap[i][y] = 9;
else if (tempMap[i][y] == 6)
break;
}
return;
}
void setWatched(void) {
// Map 복제.
int tempMap[8][8] = {};
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
tempMap[i][j] = map[i][j];
// CCTV 종류와 방향에 따라서 셋팅해보자.
for (int i = 0; i < C; i++) {
if (v[i].second == 1) { // 1번 CCTV
if (dir[i] == 1)
up(v[i].first.first, v[i].first.second, tempMap);
else if (dir[i] == 2)
right(v[i].first.first, v[i].first.second, tempMap);
else if (dir[i] == 3)
down(v[i].first.first, v[i].first.second, tempMap);
else
left(v[i].first.first, v[i].first.second, tempMap);
}
else if (v[i].second == 2) { // 2번 CCTV
if (dir[i] % 2 == 1) {
right(v[i].first.first, v[i].first.second, tempMap);
left(v[i].first.first, v[i].first.second, tempMap);
}
else {
up(v[i].first.first, v[i].first.second, tempMap);
down(v[i].first.first, v[i].first.second, tempMap);
}
}
else if (v[i].second == 3) { // 3번 CCTV
if (dir[i] == 1){
up(v[i].first.first, v[i].first.second, tempMap);
right(v[i].first.first, v[i].first.second, tempMap);
}
else if (dir[i] == 2){
right(v[i].first.first, v[i].first.second, tempMap);
down(v[i].first.first, v[i].first.second, tempMap);
}
else if (dir[i] == 3){
down(v[i].first.first, v[i].first.second, tempMap);
left(v[i].first.first, v[i].first.second, tempMap);
}
else{
left(v[i].first.first, v[i].first.second, tempMap);
up(v[i].first.first, v[i].first.second, tempMap);
}
}
else if (v[i].second == 4) { // 4번 CCTV
if (dir[i] == 1) {
up(v[i].first.first, v[i].first.second, tempMap);
right(v[i].first.first, v[i].first.second, tempMap);
left(v[i].first.first, v[i].first.second, tempMap);
}
else if (dir[i] == 2) {
up(v[i].first.first, v[i].first.second, tempMap);
right(v[i].first.first, v[i].first.second, tempMap);
down(v[i].first.first, v[i].first.second, tempMap);
}
else if (dir[i] == 3) {
right(v[i].first.first, v[i].first.second, tempMap);
down(v[i].first.first, v[i].first.second, tempMap);
left(v[i].first.first, v[i].first.second, tempMap);
}
else {
down(v[i].first.first, v[i].first.second, tempMap);
left(v[i].first.first, v[i].first.second, tempMap);
up(v[i].first.first, v[i].first.second, tempMap);
}
}
else {
up(v[i].first.first, v[i].first.second, tempMap);
right(v[i].first.first, v[i].first.second, tempMap);
down(v[i].first.first, v[i].first.second, tempMap);
left(v[i].first.first, v[i].first.second, tempMap);
}
}
ans = min(ans, getArea(tempMap));
return;
}
void BT(int c) {
if (c == C) {
setWatched();
return;
}
for (int i = 1; i <= 4; i++) {
dir.push_back(i);
BT(c + 1);
dir.pop_back();
}
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> N >> M;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++){
cin >> map[i][j];
if (1 <= map[i][j] && map[i][j] <= 5) {
v.push_back(make_pair(make_pair(i, j), map[i][j]));
C++;
}
}
BT(0);
cout << ans << '\n';
}