ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ] 15683번 감시
    알고리즘/BOJ 2020. 7. 30. 20:51

    https://www.acmicpc.net/problem/15683

     

    15683번: 감시

    스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감��

    www.acmicpc.net

     

    아이디어

    1, 위, 아래, 왼쪽, 오른쪽을 감시 할 때의 기능을 하는 함수를 각각 구현

     

    2, cctv의 종류에 따라 감시할 수 있는 방향의 모든 경우를 고려하여 dfs를 구현

     

    3, 단, 이때 주의할 점은 dfs를 구현 할 때 이전 상태로 되돌릴 때, 해당 cctv가 감시를 했던 곳만 이전 상태로 되돌려야 한다. 즉, 감시가 겹쳐있는 곳이 있기 때문에 구분을 잘 해 주워야 한다.

     

    #include <cstdio>
    #include <vector>
    #include <utility>
    using namespace std;
    
    int n, m;
    int map[9][9];
    vector<vector<int>> search;
    int res = 100;
    
    vector<pair<int,int>> up_check(int r, int c, vector<pair<int,int>> check) {
    
    	for(int i = r - 1; i >= 0; i--) {
    		if (map[i][c] == 6) break;
    		
    		if (map[i][c] == 0) {
    			map[i][c] = 7;
    			pair<int, int> insert(i, c);
    			check.push_back(insert);
    		}
    	}
    	return check;
    }
    
    vector<pair<int, int>> down_check(int r, int c, vector<pair<int,int>> check) {
    
    	for (int i = r + 1; i < n; i++) {
    		if (map[i][c] == 6) break;
    
    		if (map[i][c] == 0) {
    			map[i][c] = 7;
    			pair<int, int> insert(i, c);
    			check.push_back(insert);
    		}
    	}
    	return check;
    }
    
    vector<pair<int, int>> left_check(int r, int c, vector<pair<int, int>> check) {
    
    	for (int i = c - 1; i >= 0; i--) {
    		if (map[r][i] == 6) break;
    
    		if (map[r][i] == 0) {
    			map[r][i] = 7;
    			pair<int, int> insert(r, i);
    			check.push_back(insert);
    		}
    	}
    	return check;
    }
    
    vector<pair<int, int>> right_check(int r, int c, vector<pair<int, int>> check) {
    
    	for (int i = c + 1; i < m; i++) {
    		if (map[r][i] == 6) break;
    
    		if (map[r][i] == 0) {
    			map[r][i] = 7;
    			pair<int, int> insert(r, i);
    			check.push_back(insert);
    		}
    	}
    	return check;
    }
    
    
    void reset_location(vector<pair<int, int>> check) {
    
    	int s = check.size();
    
    	for (int i = 0; i < s; i++) {
    		map[check[i].first][check[i].second] = 0;
    	}
    }
    
    
    void dfs(int idx) {
    
    	if (idx == search.size()) {
    		int count_zero = 0;
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < m; j++) {
    				if (map[i][j] == 0) {
    					count_zero++;
    				}
    			}
    		}
    
    		if (res > count_zero) res = count_zero;
    		return;
    	}
    
    	int r = search[idx][0];
    	int c = search[idx][1];
    	int cctv = search[idx][2];
    	vector<pair<int, int>> look_location;
    
    
    	if (cctv == 1) {
    
    		//위를 감시
    		look_location = up_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    
    		//아래를 감시
    		look_location = down_check(r, c,look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//왼쪽을 감시
    		look_location = left_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//오른쪽을 감시
    		look_location = right_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    	}
    	else if (cctv == 2) {
    
    		//위아래 감시
    		look_location = up_check(r, c, look_location);
    		look_location = down_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//왼쪽오른쪽 감시
    		look_location = left_check(r, c, look_location);
    		look_location = right_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    	}
    	else if (cctv == 3) {
    
    		//위오른쪽 감시
    		look_location = up_check(r, c, look_location);
    		look_location = right_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//오른쪽 아래 감시
    		look_location = right_check(r, c, look_location);
    		look_location = down_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//아래쪽왼쪽 감시
    		look_location = left_check(r, c, look_location);
    		look_location = down_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//왼쪽위쪽 감시
    		look_location = up_check(r, c, look_location);
    		look_location = left_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    	}
    	else if (cctv == 4) {
    		//위 제외
    		look_location = right_check(r, c, look_location);
    		look_location = left_check(r, c, look_location);
    		look_location = down_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    		
    		//오른쪽 제외
    		look_location = up_check(r, c, look_location);
    		look_location = left_check(r, c, look_location);
    		look_location = down_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//아래쪽 제외 
    		look_location = right_check(r, c, look_location);
    		look_location = left_check(r, c, look_location);
    		look_location = up_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    		//왼쪽 제외
    		look_location = right_check(r, c, look_location);
    		look_location = up_check(r, c, look_location);
    		look_location = down_check(r, c, look_location);
    		dfs(idx + 1);
    		reset_location(look_location);
    		look_location.clear();
    
    
    	}
    	else if (cctv == 5) {
    
    	//전 방향 감시
    	look_location = right_check(r, c, look_location);
    	look_location = up_check(r, c, look_location);
    	look_location = down_check(r, c, look_location);
    	look_location = left_check(r, c, look_location);
    	dfs(idx + 1);
    	reset_location(look_location);
    	look_location.clear();
    
    	}
    
    }
    
    
    int main()
    {
    	int s;
    
    	scanf("%d %d", &n,&m);
    	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) {
    				vector<int> insert;
    				insert.push_back(i);
    				insert.push_back(j);
    				insert.push_back(map[i][j]);
    				search.push_back(insert);
    			}
    		}
    	}
    
    	dfs(0);
    
    
    	printf("%d\n", res);
    
    	return 0;
    }

    '알고리즘 > BOJ' 카테고리의 다른 글

    [BOJ] 17140번 이차원 배열과 연산  (0) 2020.07.31
    [BOJ] 15684번 사다리 조작  (0) 2020.07.31
    [BOJ] 14891번 톱니바퀴  (0) 2020.07.30
    [BOJ] 14890번 경사로  (0) 2020.07.26
    [BOJ] 14889 스타트와 링크  (0) 2020.07.26
Designed by Tistory.