본문 바로가기

알고리즘/백준

[백준] 15684번 사다리 조작

반응형

15684번 사다리 조작


1. 이해하기

  • 사다리에 가로선을 놓아 길을 만들어 자신이 출발한 세로선과 끝난 세로선이 같도록 해야 한다.
  • 사다리의 가로선을 모두 놓아보는 완전 탐색 문제.

2. 구현하기

  • 사다리를 타고 내려가보면서 자신이 출발한 세로선에서 끝나는 경우인지 판단.

    bool is_all_match() {
        for(int i = 0; i < N; i++) {
            int x = 0, y = i;
            while(x < H) {
                int num = map[x][y];
                if(num != 0) {
                    if(y-1 >= 0 and map[x][y-1] == num) {
                        y--;
                    } else if(y+1 < N and map[x][y+1] == num) {
                        y++;
                    }
                }
                x++;
            }
            if(y != i) return false;
        }
        return true;
    }
  • 최대 3개까지 가로선을 놓아보며 최소로 놓아도 되는 가로선이 몇개인지 찾는다.

    • 이때, 가로선을 놓아도 되는 위치를 잘 파악해야 한다.
    int solve(int cnt, int r) {
        if(cnt > 3) return MAX;
        if(is_all_match()) return cnt;
    
        int ret = MAX;
        for(int i = r; i < H; i++) {
            for(int j = 0; j < N; j++) {
                if(map[i][j] != 0) continue;
                if(j+1 < N and map[i][j+1] == 0) {
                    map[i][j] = map[i][j+1] = j+1;
                    ret = min(ret,solve(cnt+1,i));
                    map[i][j] = map[i][j+1] = 0;
                }
            }
        }
        return ret;
    }

3. 전체 코드

#include <iostream>
using namespace std;
const int MAX = 987654321;
int map[31][10];
int N,M,H;

bool is_all_match() {
    for(int i = 0; i < N; i++) {
        int x = 0, y = i;
        while(x < H) {
            int num = map[x][y];
            if(num != 0) {
                if(y-1 >= 0 and map[x][y-1] == num) {
                    y--;
                } else if(y+1 < N and map[x][y+1] == num) {
                    y++;
                }
            }
            x++;
        }
        if(y != i) return false;
    }
    return true;
}

int solve(int cnt, int r) {
    if(cnt > 3) return MAX;
    if(is_all_match()) return cnt;

    int ret = MAX;
    for(int i = r; i < H; i++) {
        for(int j = 0; j < N; j++) {
            if(map[i][j] != 0) continue;
            if(j+1 < N and map[i][j+1] == 0) {
                map[i][j] = map[i][j+1] = j+1;
                ret = min(ret,solve(cnt+1,i));
                map[i][j] = map[i][j+1] = 0;
            }
        }
    }
    return ret;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    cin >> N >> M >> H;
    for(int i = 0; i < M; i++) {
        int h,n;
        cin >> h >> n;
        h--; n--;
        map[h][n] = map[h][n+1] = n+1;
    }

    int ans = solve(0,0);
    if(ans == MAX) cout << -1 << '\n';
    else cout << ans << '\n';
    return 0;
}

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

[백준] 15686번 치킨 배달  (0) 2019.10.08
[백준] 15685번 드래곤 커브  (0) 2019.10.07
[백준] 15683번 감시  (0) 2019.10.06
[백준] 14891번 톱니바퀴  (0) 2019.10.06
[백준] 14890번 경사로  (0) 2019.10.05