#include <iostream>
#include <vector>
#include <memory.h>
#include <algorithm>
#include <queue>
#include <climits>
#define MAX_N_M 8
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
#define CCTV_MAX 6 // 1 ~ 5번
#define CASES_MAX 4
#define EMPTY 0
#define WALL 6
#define CHECK 7 // cctv 로 감시된 영역
using namespace std;
int N, M;
int board[MAX_N_M][MAX_N_M];
int cboard[MAX_N_M][MAX_N_M];
vector<pair<int, int>> cctvPos;
vector<int> table[CCTV_MAX][CASES_MAX];
vector<int> allCases[CCTV_MAX];
vector<int> cand;
int dx[4] = { -1, 1, 0, 0 };
int dy[4] = { 0, 0, -1, 1 };
bool visited[64];
void input()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
cin >> N >> M;
for (int r = 0; r < N; r++) {
for (int c = 0; c < M; c++) {
cin >> board[r][c];
if (board[r][c] > 0 && board[r][c] < 6) cctvPos.push_back(make_pair(r, c));
}
}
memset(visited, false, sizeof(visited));
}
void initCCTV()
{
table[1][0].push_back(UP);
table[1][1].push_back(DOWN);
table[1][2].push_back(LEFT);
table[1][3].push_back(RIGHT);
allCases[1].push_back(0);
allCases[1].push_back(1);
allCases[1].push_back(2);
allCases[1].push_back(3);
table[2][0].push_back(UP);
table[2][0].push_back(DOWN);
table[2][1].push_back(LEFT);
table[2][1].push_back(RIGHT);
allCases[2].push_back(0);
allCases[2].push_back(1);
table[3][0].push_back(UP);
table[3][0].push_back(RIGHT);
table[3][1].push_back(RIGHT);
table[3][1].push_back(DOWN);
table[3][2].push_back(DOWN);
table[3][2].push_back(LEFT);
table[3][3].push_back(LEFT);
table[3][3].push_back(UP);
allCases[3].push_back(0);
allCases[3].push_back(1);
allCases[3].push_back(2);
allCases[3].push_back(3);
table[4][0].push_back(LEFT);
table[4][0].push_back(UP);
table[4][0].push_back(RIGHT);
table[4][1].push_back(UP);
table[4][1].push_back(RIGHT);
table[4][1].push_back(DOWN);
table[4][2].push_back(RIGHT);
table[4][2].push_back(DOWN);
table[4][2].push_back(LEFT);
table[4][3].push_back(DOWN);
table[4][3].push_back(LEFT);
table[4][3].push_back(UP);
allCases[4].push_back(0);
allCases[4].push_back(1);
allCases[4].push_back(2);
allCases[4].push_back(3);
table[5][0].push_back(UP);
table[5][0].push_back(RIGHT);
table[5][0].push_back(DOWN);
table[5][0].push_back(LEFT);
allCases[5].push_back(0);
}
void updateMap(int sx, int sy, int dir)
{
int nx = sx + dx[dir];
int ny = sy + dy[dir];
while (true) {
if (nx < 0 || nx >= N || ny < 0 || ny >= M) break;
if (board[nx][ny] == WALL) break;
if (board[nx][ny] == EMPTY) cboard[nx][ny] = CHECK;
nx += dx[dir];
ny += dy[dir];
}
}
void startMonitor(int sx, int sy, int dirNumber)
{
int cctv = board[sx][sy];
for (auto dir : table[cctv][dirNumber]) {
updateMap(sx, sy, dir);
}
}
int countNoCheckArea()
{
int ret = 0;
for (int r = 0; r < N; r++) {
for (int c = 0; c < M; c++) {
if (cboard[r][c] == EMPTY) ret++;
}
}
return ret;
}
int getNoVisibleAreaNum()
{
memcpy(cboard, board, sizeof(board));
for (int i = 0; i < cand.size(); i++) {
int sx = cctvPos[i].first;
int sy = cctvPos[i].second;
int dirNumber = cand[i];
startMonitor(sx, sy, dirNumber);
}
return countNoCheckArea();
}
int dfs(int v)
{
if (v == cctvPos.size()) {
return getNoVisibleAreaNum();
}
int ret = INT_MAX;
for (int i = v; i < cctvPos.size(); i++) {
if (visited[i]) continue;
visited[i] = true;
int cctv = board[cctvPos[i].first][cctvPos[i].second];
for (int j = 0; j < allCases[cctv].size(); j++) {
cand.push_back(allCases[cctv][j]);
ret = min(ret, dfs(i + 1));
cand.pop_back();
}
visited[i] = false;
}
return ret;
}
int main()
{
input();
initCCTV();
cout << dfs(0) << endl;
return 0;
}
Leave a comment