728x90
반응형
https://www.acmicpc.net/problem/15683
15683번: 감시
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감
www.acmicpc.net
최종 코드
GitHub - hwayeon351/BEAKJOON-Algorithms: 백준 알고리즘 소스 코드 모음
백준 알고리즘 소스 코드 모음. Contribute to hwayeon351/BEAKJOON-Algorithms development by creating an account on GitHub.
github.com
//
// main.cpp
// BJ15683
//
// Created by 최화연 on 2022/04/21.
//
#include <iostream>
#include <vector>
using namespace std;
int N, M;
int office[8][8] = {0, };
vector<pair<pair<int, int>, int>> cctvs;
int hole = 0;
int dr[4] = {0, -1, 0, 1};
int dc[4] = {-1, 0, 1, 0};
vector<vector<int>> cctv[6] = {
{},
{{2}, {1}, {0}, {3}},
{{0, 2}, {1, 3}},
{{1, 2}, {2, 3}, {3, 0}, {0, 1}},
{{0, 1, 2}, {1, 2, 3}, {2, 3, 0}, {3, 0, 1}},
{{0, 1, 2, 3}}
};
vector<int> direction;
int answer = 64;
int operate_cctvs() {
int visits[8][8] = {0, };
int cnt = 0;
for (int i=0; i<cctvs.size(); i++) {
for (int d=0; d<cctv[cctvs[i].second][direction[i]].size(); d++) {
int dir = cctv[cctvs[i].second][direction[i]][d];
int r = cctvs[i].first.first + dr[dir];
int c = cctvs[i].first.second + dc[dir];
while (r >= 0 && r < N && c >= 0 && c < M) {
if (office[r][c] == 6) break;
if (office[r][c] == 0 && !visits[r][c]) {
visits[r][c] = 1;
cnt ++;
}
r += dr[dir];
c += dc[dir];
}
}
}
return hole - cnt;
}
void choose_direction(int i) {
if (i == cctvs.size()) {
int result = operate_cctvs();
if (answer > result) answer = result;
return;
}
for (int d=0; d<cctv[cctvs[i].second].size(); d++) {
direction.push_back(d);
choose_direction(i+1);
direction.pop_back();
}
}
int main(int argc, const char * argv[]) {
cin >> N >> M;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
cin >> office[i][j];
if (office[i][j] == 0) hole ++;
else if (office[i][j] >= 1 && office[i][j] <= 5) {
cctvs.push_back({{i, j}, office[i][j]});
}
}
}
choose_direction(0);
cout << answer << endl;
return 0;
}
풀이 과정
풀이 시간 42분
#include <iostream>
#include <vector>
using namespace std;
int N, M;
int office[8][8] = {0, };
vector<pair<pair<int, int>, int>> cctvs;
int hole = 0;
int dr[4] = {0, -1, 0, 1};
int dc[4] = {-1, 0, 1, 0};
vector<vector<int>> cctv[6] = {
{},
{{2}, {1}, {0}, {3}},
{{0, 2}, {1, 3}},
{{1, 2}, {2, 3}, {3, 0}, {0, 1}},
{{0, 1, 2}, {1, 2, 3}, {2, 3, 0}, {3, 0, 1}},
{{0, 1, 2, 3}}
};
vector<int> direction;
int answer = 64;
int operate_cctvs() {
int visits[8][8] = {0, };
int cnt = 0;
for (int i=0; i<cctvs.size(); i++) {
for (int d=0; d<cctv[cctvs[i].second][direction[i]].size(); d++) {
int dir = cctv[cctvs[i].second][direction[i]][d];
int r = cctvs[i].first.first + dr[dir];
int c = cctvs[i].first.second + dc[dir];
while (r >= 0 && r < N && c >= 0 && c < M) {
if (office[r][c] == 6) break;
if (office[r][c] == 0 && !visits[r][c]) {
visits[r][c] = 1;
cnt ++;
}
r += dr[dir];
c += dc[dir];
}
}
}
return hole - cnt;
}
void choose_direction(int i) {
if (i == cctvs.size()) {
int result = operate_cctvs();
if (answer > result) answer = result;
return;
}
for (int d=0; d<cctv[cctvs[i].second].size(); d++) {
direction.push_back(d);
choose_direction(i+1);
direction.pop_back();
}
}
int main(int argc, const char * argv[]) {
cin >> N >> M;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
cin >> office[i][j];
if (office[i][j] == 0) hole ++;
else if (office[i][j] >= 1 && office[i][j] <= 5) {
cctvs.push_back({{i, j}, office[i][j]});
}
}
}
choose_direction(0);
cout << answer << endl;
return 0;
}
이전 풀이
풀이 시간 2시간 12분
//
// main.cpp
// BJ15683
//
// Created by Hwayeon on 2021/08/03.
//
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int N, M;
int office[8][8] = {0, };
int c_office[8][8] = {0, };
//0-우, 1-하, 2-좌, 3-상
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
//cctv1 ~ cctv5가 감시할 수 있는 방향 정보를 담은 벡터
//cctv_info[c_num][d_num][d]
vector<vector<vector<int>>> cctv_info = {
{{}},
//cctv1
{{0}, {1}, {2}, {3}},
//cctv2
{{0,2}, {1,3}},
//cctv3
{{0,3}, {1,0}, {1,2}, {2,3}},
//cctv4
{{0,2,3}, {0,1,3}, {0,1,2}, {1,2,3}},
//cctv5
{{0,1,2,3}}
};
//설치된 cctv의 번호와 위치를 담는 벡터
//cctvs[i] = {c_num, {x, y}}
vector<pair<int, pair<int, int>>> cctvs;
int answer = 64;
int cal_blind_spot(){
int cnt = 0;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
//빈 칸인 경우 사각지대이므로 카운팅
if(c_office[i][j] == 0){
cnt ++;
}
}
}
return cnt;
}
void copy_office(){
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
c_office[i][j] = office[i][j];
}
}
}
void turn_direction(){
//cctv가 0대인 경우, 빈 칸 개수 = answer
if(cctvs.size()==0){
copy_office();
answer = cal_blind_spot();
return;
}
//모든 시시티비 방향에 대한 경우의 수를 구한다 -> bfs 알고리즘 적용
//각 cctv의 방향을 담을 큐
queue<vector<pair<int, int>>> q;
//첫번째 cctv의 각 방향 정보를 담은 벡터를 큐에 삽입
vector<pair<int, int>> cc;
int c_num = cctvs[0].first;
int d_kinds = int(cctv_info[c_num].size());
int d_num;
for(int i=0; i<d_kinds; i++){
cc.clear();
cc.push_back({c_num, i});
q.push(cc);
}
while(!q.empty()){
cc.clear();
cc = q.front();
q.pop();
//cctv들의 방향이 모두 정해진 경우, 사각지대 계산
if(cc.size() == cctvs.size()){
copy_office();
for(int i=0; i<cctvs.size(); i++){
c_num = cc[i].first;
d_num = cc[i].second;
int x = cctvs[i].second.first;
int y = cctvs[i].second.second;
for(int d=0; d<cctv_info[c_num][d_num].size(); d++){
int nx = x+dx[cctv_info[c_num][d_num][d]];
int ny = y+dy[cctv_info[c_num][d_num][d]];
while(true){
//사무실을 벗어난 경우
if(ny < 0 or ny > N-1 or nx < 0 or nx > M-1) break;
//벽인 경우
if(c_office[ny][nx] == 6) break;
//빈 칸인 경우
else if(c_office[ny][nx] == 0) c_office[ny][nx] = 9;
nx += dx[cctv_info[c_num][d_num][d]];
ny += dy[cctv_info[c_num][d_num][d]];
}
}
}
int b_spot = cal_blind_spot();
if(answer > b_spot) answer = b_spot;
continue;
}
//다음 cctv의 방향을 정하여 큐에 삽입
c_num = cctvs[int(cc.size())].first;
d_kinds = int(cctv_info[c_num].size());
for(int i=0; i<d_kinds; i++){
cc.push_back({c_num, i});
q.push(cc);
cc.pop_back();
}
}
}
int main(int argc, const char * argv[]) {
cin >> N >> M;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cin >> office[i][j];
//cctv인 경우
if(office[i][j] >= 1 and office[i][j] <= 5){
cctvs.push_back({office[i][j], {j, i}});
}
}
}
turn_direction();
cout << answer << endl;
return 0;
}
//시간복잡도 = O(n^2), 공간복잡도 = O(n^2)
728x90
반응형
'코테 노트 > 백준' 카테고리의 다른 글
백준 15686 치킨 배달 C++ (0) | 2021.08.04 |
---|---|
백준 1463 1로 만들기 Python3 (0) | 2021.08.04 |
백준 14500 테트로미노 C++ (0) | 2021.07.22 |
백준 14499 주사위 굴리기 C++ (0) | 2021.07.21 |
백준 3190 뱀 C++ (0) | 2021.07.19 |