백준: Class 4 - 2096, 2206, 2638

3 분 소요


</br> 클래스 4 계속
</br>

2096: 내려가기

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

    for(int i = 0; i < n; i++){
        cin >> nums[i][0] >> nums[i][1] >> nums[i][2];
    }

    int a = nums[0][0], b = nums[0][1], c = nums[0][2];
    int am = nums[0][0], bm = nums[0][1], cm = nums[0][2];
    for(int i = 1; i < n; i++){
        int aa, bb, cc;
        aa = nums[i][0] + max(a, b);
        bb = nums[i][1] + max({a, b, c});
        cc = nums[i][2] + max(b, c);
        a = aa; b = bb; c = cc;

        aa = nums[i][0] + min(am, bm);
        bb = nums[i][1] + min({am, bm, cm});
        cc = nums[i][2] + min(bm, cm);
        am = aa; bm = bb; cm = cc;
    }

    cout << max({a, b, c}) << ' ';
    cout << min({am, bm, cm}) << '\n';

메모리 제한 4MB에 시간 제한 1초면 플렉스하며 코딩은 못하겠네
4MB면 인트 100만 개 정도다 근데 n이 10만이면 크게 상관있나?
아무튼 가난하게 짜 보면 dp 테이블 만드는 건 공간 사치니까 그냥 현재 열 별 최대 점수를 저장하는 정수만 3개 선언하자
이왕 포문 돌리는 거 최대랑 최소도 같이 구하자
쉬운데 골드 4라니 좋구나
</br>

2206: 벽 부수고 이동하기

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

    queue<P> q;
    P p = {0, 0, 1, 1};
    q.push(p);
    visited[1][0][0] = 1;
    int ans = -1;
    while( q.size() ){
        int x = q.front().x;
        int y = q.front().y;
        int w = q.front().w;
        int d = q.front().d;
        q.pop();
        if( x == n-1 && y == m-1 ){
            ans = d;
            break;
        }
        for(int i = 0; i < 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if( nx < 0 || n <= nx || ny < 0 || m <= ny ) continue;
            if( mmap[nx][ny] == 1 ){
                if( w && visited[0][nx][ny] == 0 ){
                    P p = {nx, ny, 0, d+1};
                    q.push(p);
                    visited[0][nx][ny] = 1;
                }
            }
            else if( visited[w][nx][ny] == 0 ){
                P p = {nx, ny, w, d+1};
                q.push(p);
                visited[w][nx][ny] = 1;
            }
        }
    }
    cout << ans << endl;

나는 bfs가 좋아
위치 x, 위치 y, 벽 w, 거리 d를 묶어서 큐에 저장한다
visited[] 배열은 현재 벽을 부술 수 있는 지, 아닌 지로 구분해서 int visited[2][1001][1001];로 선언했다.
만약 1인데 지금 기회가 있으면 부수고 아님 말고 하게 하면 된다
</br>

2638: 치즈

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

void isOut(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            outside[i][j] = 0;
        }
    }
    queue< pair<int, int> > q;
    q.push(make_pair(0, 0));
    outside[0][0] = 1;
    while( q.size() ){
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if( nx < 0 || n <= nx || ny < 0 || m <= ny ) continue;
            if( cheese[nx][ny] == 0 && outside[nx][ny] == 0 ){
                q.push(make_pair(nx, ny));
                outside[nx][ny] = 1;
            }
        }
    }
}

bool func(){
    isOut();
    stack< pair<int, int> > st;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if( cheese[i][j] == 0 ) continue;
            int cnt = 0;
            for(int k = 0; k < 4; k++){
                int nx = i + dx[k];
                int ny = j + dy[k];
                if( nx < 0 || n <= nx || ny < 0 || m <= ny ) continue;
                if( cheese[nx][ny] == 0 && outside[nx][ny] == 1 ) cnt++;
                if( cnt == 2 ) break;
            }
            if( cnt == 2 ) st.push(make_pair(i, j));
        }
    }
    while( st.size() ){
        cheese[st.top().first][st.top().second] = 0;
        st.pop();
        chee--;
    }
    if( chee == 0 ) return true;
    return false;
}

// in main()
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> cheese[i][j];
            if( cheese[i][j] == 1 ) chee++;
        }
    }
    if( chee == 0 ){
        cout << 0 << endl;
        return 0;
    }
    int d = 1;
    while( 1 ){
        if( func() ) break;
        d++;
    }
    cout << d << endl;

재밌다
안쪽 공기를 어떻게 알지가 고민 됐는데 생각해 보니까 바깥 공기를 bfs로 다 표시해 놓으면 되겠더라
생각해내니까 이전의 내가 멍청해 보인다

그 다음은 쉽다 그냥 바깥 공기와 2개 닿는 것들을 한 번에 0으로 바꾸면 된다.

지금 보니 바깥 공기 배열은 굳이 매번 초기화 안 해도 될 것 같다
처음 한 번만 초기화 후 (0, 0)에서 시작해서 만들어 놓은 후, 그 다음 부터는 바깥 공기에 체크 안 된 부분만 확인해 주면 되겠다
</br>


골드 1이 되었다~~ 물렙이지만 기뻐
</br>

댓글남기기