Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Python
- BOJ14889
- DP
- 재귀함수
- 26008
- 브루트포스
- 재귀
- sw expert academy
- D1
- 15662
- BOJ
- dart
- 회전하는큐
- Crossfit
- 1로만들기2
- C++
- 삼성
- 동적프로그래밍
- 서울에서경산까지
- 1781
- 14863
- 백준
- 크로스핏
- 15353
- 그리디
- 4811
- Flutter
- 해시해킹
- 스택
- spring boot
Archives
- Today
- Total
곧죽어도 콛잉
[구현 / BOJ 15683 / C++] 감시 본문
https://www.acmicpc.net/problem/15683
15683번: 감시
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감
www.acmicpc.net
아이코.. 벽개수를 빼는거를 잊어버렸다 이것때메 개고생했다아..
벽은 사각지대에 포함하면 안됩니다~~!
cctv개수가 8개밖에 안되므로 문제는 진짜 있는 그대로 구현만 해주면 된다.
약간 노가다로 풀어서 좀 화가나긴하는데 그래도 여차저차하면 어떻게든 된다 ..
이건진짜 시간싸움인 문제 같다.
코드 중에 감시(overwatch) 부분 해결하는 방법을 생각하기가 좀 까다로웠다.
그냥 노가다로 하면되는데 최대한 간단하게 해보자하고 머리쓰다가 더 복잡해진 느낌이다.
그냥 if문 노가다하는게 더 깔끔할지도.
예전에는 손도 못댔던 문제였는데 다시 해보니깐 잘 풀려서 다행이다 ㅎㅎ..
#include <bits/stdc++.h>
using namespace std;
int N, M, bd[9][9], res=INT_MAX;
int vis[9][9];
struct cctv{
int no; // 종류
int dir; // 방향
pair<int,int> pos;
};// 0 1 2 3 오른쪽 아래 왼쪽 위쪽
vector<cctv> cctvs;
// 0 1 2 3 오른쪽 아래 왼쪽 위쪽
int dy[4] = {0, 1, 0, -1};
int dx[4] = {1, 0, -1, 0};
void check(){ // 사각지대 확인
int chk=0;
for(int i = 0 ; i < N ; i++){
for(int j = 0 ; j < M ; j++){
if(vis[i][j]==0 && bd[i][j]!=6) chk++;
}
}
res = min(chk, res);
return;
}
void overwatch(int d, int pos_y, int pos_x){ // 감시
if(d==2 || d==0) { // 오른쪽 왼쪽
for(int k = pos_x ; ; k+=dx[d]){
if(k > M || k < 0) break;
if(bd[pos_y][k]==6) {vis[pos_y][k]=6; break;} // 벽을 만날시 중단
vis[pos_y][k] = -1;
}
}
else { // 위 아래
for(int k = pos_y ; ; k+=dy[d]){
if(k > N || k < 0) break;
if(bd[k][pos_x]==6){vis[k][pos_x]=6; break;} // 벽을 만날시 중단
vis[k][pos_x] = -1;
}
}
return;
}
void go(int st, vector<cctv> v){
if(v.size()==cctvs.size()){
memset(vis, 0, sizeof(vis));
for(auto i : v){ // 각 cctv에 대해 감시
int pos_y = i.pos.first;
int pos_x = i.pos.second;
int d = i.dir;
switch (i.no) {
case 1:
overwatch(d, pos_y, pos_x);
break;
case 2:
if(d==2 || d==0) {
overwatch(2, pos_y, pos_x);
overwatch(0, pos_y, pos_x);
} else{
overwatch(1, pos_y, pos_x);
overwatch(3, pos_y, pos_x);
}
break;
case 3:
if(d==0) {
overwatch(3, pos_y, pos_x);
overwatch(0, pos_y, pos_x);
} else{ // 3 2 2 1 1 0
overwatch(d, pos_y, pos_x);
overwatch(d-1, pos_y, pos_x);
}
break;
case 4:
// 0 1 2 , 1 2 3
if(d==0 || d== 1){
overwatch(d, pos_y, pos_x);
overwatch(d+1, pos_y, pos_x);
overwatch(d+2, pos_y, pos_x);
} else{ // 0 2 3 , 0 1 3
overwatch(0, pos_y, pos_x);
overwatch(4-d, pos_y, pos_x);
overwatch(3, pos_y, pos_x);
}
break;
case 5:
overwatch(0, pos_y, pos_x);
overwatch(1, pos_y, pos_x);
overwatch(2, pos_y, pos_x);
overwatch(3, pos_y, pos_x);
break;
}
}
check(); // 사각지대 확인
return;
}
// cctv 선택 후 회전시키기
for(int i = st + 1 ; i < cctvs.size() ; i++){
cctvs[i].dir=0; // 오른쪽
v.push_back(cctvs[i]);
go(i, v);
v.pop_back();
cctvs[i].dir=1; // 아래쪽
v.push_back(cctvs[i]);
go(i, v);
v.pop_back();
cctvs[i].dir=2; // 왼쪽
v.push_back(cctvs[i]);
go(i, v);
v.pop_back();
cctvs[i].dir=3; // 위쪽
v.push_back(cctvs[i]);
go(i, v);
}
return;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N >> M;
for(int i = 0 ; i < N ; i++){
for(int j = 0 ; j < M; j++){
cin >> bd[i][j];
if(bd[i][j] < 6 && bd[i][j]){
cctvs.push_back({bd[i][j], 0, {i, j}});
}
}
}
vector<cctv> v;
go(-1, v);
cout << res << '\n';
}
태그 : 1780, BOJ, C++, 백준, 재귀, 재귀함수, 종이의 개수
'Coding Test > C++' 카테고리의 다른 글
[이분탐색 / BOJ 2343 / C++] 기타레슨 (0) | 2023.07.12 |
---|---|
[구현 / BOJ 2170 / C++] 선긋기 (0) | 2023.07.12 |
[구현 / BOJ 16236 / C++] 아기상어 (0) | 2023.07.11 |
[구현 / BOJ 15662 / C++] 톱니바퀴 (2) (0) | 2023.06.29 |
[구현 / BOJ 14888 / C++] 연산자 끼워넣기 (0) | 2023.06.28 |
Comments