백준: Silver1③ - 1174, 1189, 1245

2 분 소요


</br> 이제 얼마 안 남은 것 같다
</br>

1174: 줄어드는 숫자

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

n번째 줄어드는 수 찾기

void func(int k, unsigned long long ans, int pos){
    if( pos == 1 ){
        cnt++;
        if( cnt == n ) cout << ans << endl;
        return;
    }
    for(int i = 0; i < k; i++){
        func(i, ans*10+ i, pos-1);
        if( cnt == n ) return;
    }

}

// int main()
    if( n <= 10 ){
        cout << n-1 << endl;
        return 0;
    }

    cnt = 10;
    int pos = 2;
    while( cnt < n ){
        if( pos == 11 ){
            cout << -1 << endl;
            return 0;
        }
        for(int i = 1; i < 10; i++){
            func(i, (unsigned long long)i, pos);
            if( cnt == n ) break;
        }
        pos++;
    }

그냥 for문으로 1씩 더하면서 줄어드는 숫자인지 확인하면 시간 초과 난다.
1 부터 10까지는 다 가능하므로 n-1을 출력하고 종료한다.
이후로

11 12 13 14 15 16 ...
10 20 21 30 31 32 ...

와 같이 되므로, 재귀를 통해 구할 수 있다.
참고로 줄어드는 수의 최대가 9876543210 이기 때문에, n이 만약 얘를 구한 거보다 더 큰 애라면 -1을 출력하고 종료해 줘야 한다.
</br>

1189: 컴백홈

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

길이가 k인 집가는 길 찾기

void func(int i, int j, int d){
    check[i][j] = d;
    if( d == k ){
        if( i == 1 && j == c ){
            cnt++;
        }
        check[i][j] = 0;
        return;
    }
    if( mmap[i-1][j] && !check[i-1][j] ){
        func(i-1, j, d+1);
    }
    if( mmap[i][j+1] && !check[i][j+1] ){
        func(i, j+1, d+1);
    }
    if( mmap[i+1][j] && !check[i+1][j] ){
        func(i+1, j, d+1);
    }
    if( mmap[i][j-1] && !check[i][j-1] ){
        func(i, j-1, d+1);
    }
    check[i][j] = 0;
}

간단한 dfs로 찾을 수 있다. 거리가 k보다 넘을 것 같으면 자르니까 백트래킹이 더 가깝나 싶고…
그냥 갈 수 있는 지 보고, 갈 수 있으면 가기
</br>

1245: 농장 관리

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

산봉우리 몇 갠지 찾기

void func2(int x, int y, int d){
    for(int i = 0; i < 8; i++){
        int xx = x + moveI[i];
        int yy = y + moveJ[i];
        if( mmap[xx][yy] <= d && !check[xx][yy] ){
            check[xx][yy] = 1;
            func2(xx, yy, mmap[xx][yy]);
        }
    }
}
bool func(int x, int y, int d){
    bool b = true;
    for(int i = 0; i < 8; i++){
        int xx = x + moveI[i];
        int yy = y + moveJ[i];
        if( mmap[xx][yy] > d ){
            b = false;
        }
        else if( mmap[xx][yy] < d && !check[xx][yy] ){
            check[xx][yy] = 1;
            func2(xx, yy, mmap[xx][yy]);
        }
        else if( mmap[xx][yy] == d && !check[xx][yy] ){
            check[xx][yy] = 1;
            if( !func(xx, yy, d) ) b = false;
        }

    }
    return b;
}

// in main()
    int cnt = 0;
    for(int i = 1; i < n+1; i++){
        for(int j = 1; j < m+1; j++){
            if( mmap[i][j] > 0 && !check[i][j] ){
                check[i][j] = 1;
                if( func(i, j, mmap[i][j]) ) cnt++;
            }
        }
    }
    cout << cnt << endl;

이것도 dfs로 풀었다
하나 씩 검사하는데, 만약 이미 들른 곳이면 건너 뛴다.
인접한 곳들이 만약 현재 보다 더 크다면 산봉우리가 아니므로 false를 리턴한다.
만약 현재와 같다면 그 곳에서 다시 func()을 수행한다.
만약 현재보다 작다면 이후에 산봉우리인지 확인할 필요가 없으므로 func2()를 수행해 전부 체크해 준다.
</br>


5문제 남았다~~
</br>

댓글남기기