코테 노트/백준

백준 15684 사다리 조작 C++

화요밍 2021. 8. 11. 20:00
728x90
반응형

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

 

15684번: 사다리 조작

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

www.acmicpc.net

 

최종 코드

 

GitHub - hwayeon351/BEAKJOON-Algorithms: 백준 알고리즘 소스 코드 모음

백준 알고리즘 소스 코드 모음. Contribute to hwayeon351/BEAKJOON-Algorithms development by creating an account on GitHub.

github.com

//
//  main.cpp
//  BJ15684
//
//  Created by 최화연 on 2022/04/23.
//

#include <iostream>
using namespace std;

int N, M, H;
int ladder[31][20] = {0, };

int answer = -1;

bool check_ladder() {
    bool check = true;
    for (int c=1; c<=N; c++) {
        int col = 2*(c-1)+1;
        int row = 1;
        while (row <= H) {
            //오른쪽 체크
            if (col < 2*(N-1)+1 && ladder[row][col+1]) {
                col += 2;
            }
            //왼쪽 체크
            else if (col > 1 && ladder[row][col-1]) {
                col -= 2;
            }
            row ++;
        }
        if (col == 2*(c-1)+1) continue;
        check = false;
        break;
    }
    return check;
}

void add_lines(int cnt, int col, int row, int num) {
    if (answer == num) return;
    if (cnt == num) {
        if (check_ladder()) {
            answer = num;
        }
        return;
    }
    
    for (int c=1; c<N; c++) {
        int nc = 2*(c-1)+1;
        int rr = row;
        if (c < col) rr = row+1;
        for (int r=rr; r<=H; r++) {
            if (ladder[r][nc+1]) continue;
            ladder[r][nc+1] = 1;
            if (c == N-1) add_lines(cnt+1, 1, r+1, num);
            else add_lines(cnt+1, c+1, r, num);
            ladder[r][nc+1] = 0;
        }
    }
}

int main(int argc, const char * argv[]) {
    cin >> N >> M >> H;
    for (int i=0; i<M; i++) {
        int a, b;
        cin >> a >> b;
        ladder[a][2*(b-1)+2] = 1;
    }
    
    for (int c=1; c<=N; c++) {
        int col = 2*(c-1)+1;
        for (int r=1; r<=H; r++) {
            ladder[r][col] = 1;
        }
    }
    
    if (M == 0 || check_ladder()) cout << 0 << endl;
    else {
        for (int i=1; i<=3; i++) {
            if (answer != -1) break;
            add_lines(0, 1, 1, i);
        }
        
        cout << answer << endl;
    }
    
    return 0;
}

풀이 과정

풀이 시간 1시간 8분

#include <iostream>
using namespace std;

int N, M, H;
int ladder[31][20] = {0, };

int answer = -1;

bool check_ladder() {
    bool check = true;
    for (int c=1; c<=N; c++) {
        int col = 2*(c-1)+1;
        int row = 1;
        while (row <= H) {
            //오른쪽 체크
            if (col < 2*(N-1)+1 && ladder[row][col+1]) {
                col += 2;
            }
            //왼쪽 체크
            else if (col > 1 && ladder[row][col-1]) {
                col -= 2;
            }
            row ++;
        }
        if (col == 2*(c-1)+1) continue;
        check = false;
        break;
    }
    return check;
}

void add_lines(int cnt, int col, int row, int num) {
    if (answer == num) return;
    if (cnt == num) {
        if (check_ladder()) {
            answer = num;
        }
        return;
    }
    
    for (int c=1; c<N; c++) {
        int nc = 2*(c-1)+1;
        int rr = row;
        if (c < col) rr = row+1;
        for (int r=rr; r<=H; r++) {
            if (ladder[r][nc+1]) continue;
            ladder[r][nc+1] = 1;
            if (c == N-1) add_lines(cnt+1, 1, r+1, num);
            else add_lines(cnt+1, c+1, r, num);
            ladder[r][nc+1] = 0;
        }
    }
}

int main(int argc, const char * argv[]) {
    cin >> N >> M >> H;
    for (int i=0; i<M; i++) {
        int a, b;
        cin >> a >> b;
        ladder[a][2*(b-1)+2] = 1;
    }
    
    for (int c=1; c<=N; c++) {
        int col = 2*(c-1)+1;
        for (int r=1; r<=H; r++) {
            ladder[r][col] = 1;
        }
    }
    
    if (M == 0 || check_ladder()) cout << 0 << endl;
    else {
        for (int i=1; i<=3; i++) {
            if (answer != -1) break;
            add_lines(0, 1, 1, i);
        }
        
        cout << answer << endl;
    }
    
    return 0;
}

이전 풀이

//
//  main.cpp
//  BJ15684
//
//  Created by Hwayeon on 2021/08/11.
//

#include <iostream>
using namespace std;

int N, M, H;

//사다리의 정보를 담는 배열
//사다리의 왼쪽과 오른쪽을 탐색해야 하므로 N+1, H+1 크기로 할당
//ladder[r][c] = c번째 세로줄에 r번째 가로줄의 상태
//1. ladder[r][c] = 1 -> c와 c+1을 이어주는 가로줄, c기준으로 오른쪽에 사다리가 설치되어 있는 상태
//2. ladder[r][c] = 0 && ladder[r][c-1] = 1 -> c와 c-1을 이어주는 가로줄, c기준으로 왼쪽에 사다리가 설치되어 있는 상태
//3.ladder[r][c] = 0 && ladder[r][c-1] = 0 -> c번째 세로줄에 r번째 가로줄이 없는 상태
int ladder[32][12] = {0, };
int min_line = -1;

//T(n) = N*H
bool check_ladder(){
    for(int c=1; c<=N; c++){
        int now_c = c;
        for(int r=1; r<=H; r++){
            //왼쪽으로 가야하는 경우
            if(ladder[r][now_c] == 0 && ladder[r][now_c-1] == 1){
                now_c--;
            }
            //오른쪽으로 가야하는 경우
            else if(ladder[r][now_c] == 1){
                now_c++;
            }
        }
        //i번 세로선의 i번 결과가 아닌 경우 실패
        if(c != now_c) return false;
    }
    return true;
}

//T(n) = V+E = N*H + (N+1)*H
void install_line(int cnt, int n, int row, int col){
	//n개의 가로줄을 모두 설치한 경우
    if(cnt == n){
        //사다리 조작이 성공적인 경우
        if(check_ladder()){
            min_line = n;
        }
        return;
    }
    //가로줄 설치
    for(int r=row; r<=H; r++){
    	//r이 이전에 설치한 가로줄 번호인 row와 같다면, 세로줄을 col부터 탐색한다
    	//r이 row보다 큰 경우, 세로줄을 1부터 탐색한다
    	if(r > row+1) col = 1;
        for(int c=1; c<=N; c++){
        	//가로줄은 연속되거나 겹치면 안되기 때문에, 현재 위치와 양 옆에 가로줄이 있는지 확인
            if(ladder[r][c]==0 && ladder[r][c-1] == 0 && ladder[r][c+1] == 0){
                ladder[r][c] = 1;
                //현재 설치한 세로줄의 다음번 세로줄에는 사다리를 설치할 수 없으므로 col을 c+2로 한다
                install_line(cnt+1, n, r, c+2);
                ladder[r][c] = 0;
            }
        }
    }
}

int main(int argc, const char * argv[]) {
    cin >> N >> M >> H;
    for(int i=0; i<M; i++){
        int col, row;
        cin >> row >> col;
        //col과 col+1이 연결되어 있는 가로줄
        ladder[row][col] = 1;
    }
    for(int i=0; i<=3; i++){
    	//더 적은 가로줄을 설치하여 조작 가능하므로 break
        if(min_line != -1) break;
        install_line(0, i, 1, 1);
    }
    cout << min_line << endl;
    
    return 0;
}
#시간복잡도 = T((N*H+(N+1)*H)*N*H) -> O(n^4), 공간복잡도 = O(n^2)
728x90
반응형

'코테 노트 > 백준' 카테고리의 다른 글

백준 15685 드래곤 커브 C++  (0) 2021.08.12
백준 13904 과제 Python3  (0) 2021.08.11
백준 1092 배 Python3  (0) 2021.08.11
백준 21610 마법사 상어와 비바라기 C++  (0) 2021.08.10
백준 1309 동물원 Python3  (0) 2021.08.09