ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ] 15684번 사다리 조작
    알고리즘/BOJ 2020. 7. 31. 16:38

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

     

    15684번: 사다리 조작

    사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선

    www.acmicpc.net

    처음에는 단순한 dfs방법으로 풀릴 줄 알았지만 시간 초과로 인하여 오래 걸렸던 문제이다.

     

    문제의 핵심 조건

    1, 가로선이 연속적으로 일직선이 될 수는 없다.

     

    2, 가로선이 겹치는 경우는 존재하지 않는다.

     

    3, 정답이 3보다 크면 -1을 출력한다.

     

    아이디어

    1, dfs방식으로 다리를 놓을 수 있는 경우의 수를 탐색한다.

     

    2, 문제의 조건에서 "정답이 3보다 크면 -1을 출력한다."는 조건으로 인하여 탐색 시간을 줄일 수 있다.

    - 최소값을 찾는 문제이므로 정답은 0, 1, 2, 3, -1이 될 수 있는데 0부터 시작하여 해당 경우에 맞는 답을 찾으면 탐색을 종료한다.

     

    -  위와 같은 방법을 사용하지 않을 시 dfs방식으로 답을 찾게 될 경우를 생각해 보자

    예를 들어, dfs내에서 백 트래킹 방식으로 현재 찾은 기대값을 기준으로 탐색 여부를 판단하게 된다면 현재 찾은 최솟값이 2이면 2 이하인 정답을 계속적으로 찾게 된다.

    계속 탐색을 진행하던 도중 1인 답이 나오면 이때까지 정답이 2인 경우를 찾게되는 계산이 불필요하게 들어가기 때문에  시간 초과 결과를 받게 된다.

     

    3, <참고>

    - 9프로대에서 "틀렸습니다" 결과를 받게 되었는데 하나의 세로선에도 여러 개의 가로선을 다른 가로선 위치에 넣어 줄 수 있는 것을 고려를 처음에 하지 못하였다.

     

    #include <cstdio>
    #include <vector>
    #include <utility>
    using namespace std;
    
    
    int map[31][12][12];//첫번쨰 인자는 가로선의 개수, 두번째와 세번째는 이어진 것
    int put_check[12];
    
    int n = 0, m = 0, h = 0;
    
    
    int res = -1;
    
    bool check_correct() {
    
    	int current_location;
    
    	for (int i = 1; i <= n; i++) {
    		current_location = i;
    		//사다리를 타기 시작
    		for (int j = 1; j <= h; j++) {
    			if (current_location + 1 <= n) {
    				if (map[j][current_location][current_location + 1] == 1) {
    					current_location = current_location + 1;
    					continue;
    				}
    			}
    			if (current_location - 1 > 0) {
    				if (map[j][current_location - 1][current_location] == 1) {
    					current_location = current_location - 1;
    					continue;
    				}
    			}
    		}
    
    		//최종적으로 같지 않다면 false를 반환
    		if (current_location != i) return false;
    
    	}
    	return true;
    }
    
    
    
    void dfs(int input_cnt, int start_verticle_line, int cut_line) {
    
    
    	if (cut_line == input_cnt) {
    
    		if (check_correct()) {
    			res = cut_line;
    			return;
    
    		}
    		else {
    			return;
    		}
    	}
    
    
    	//선을 하나 추가하여 조사를 진행함
    	for (int i = start_verticle_line; i <= n; i++) {
    		for (int j = 1; j <= h; j++) {
    			if (res != -1) return;
    
    			if (i - 1 > 0) {
    				if (map[j][i - 1][i] == 1) continue;
    			}
    
    			//이미 이어져 있는 곳인지 체크
    			if (i + 1 <= n) {
    				if (map[j][i][i + 1] == 1) continue;
    			}
    
    			//해당 경우가 아니라면 선을 놓고 조사를 진행
    			map[j][i][i + 1] = 1;
    			map[j][i + 1][i] = 1;
    			dfs(input_cnt + 1, i,cut_line);
    			map[j][i][i + 1] = 0;
    			map[j][i + 1][i] = 0;
    
    		}
    	}
    
    
    }
    
    int main()
    {
    	int temp1, temp2;
    	scanf("%d %d %d", &n, &m, &h);
    	for (int i = 0; i < m; i++) {
    		scanf("%d %d", &temp1, &temp2);
    		map[temp1][temp2][temp2 + 1] = 1;
    		map[temp1][temp2 + 1][temp2] = 1;
    	}
    
    	for (int i = 0; i <= 3; i++) {
    		dfs(0,1,i);
    		if (res != -1) break;
    	}
    
    	printf("%d\n", res);
    
    	return 0;
    }

     

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

    [BOJ] 17837번 새로운 게임2  (0) 2020.08.04
    [BOJ] 17140번 이차원 배열과 연산  (0) 2020.07.31
    [BOJ] 15683번 감시  (0) 2020.07.30
    [BOJ] 14891번 톱니바퀴  (0) 2020.07.30
    [BOJ] 14890번 경사로  (0) 2020.07.26
Designed by Tistory.