백준: Gold5③ - 1091, 1092, 1107

2 분 소요


</br> 계속 계속
</br>

1091: 카드 섞기

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

플레이어 0, 1, 2에게 카드 정해서 주기

bool chk(){
    for(int i = 0; i < d.size(); i++){
        if( !(m[i%3].count(d[i])) ) return false;
    }
    return true;
}

// in main()
    for(int i = 0; i < n; i++){
        d[i] = i;
        ori[i] = i;
    }

    int cnt = 0;
    while( !chk() ){
        if( ori == d && cnt ){
            cout << -1 << endl;
            return 0;
        }
        for(int i = 0; i < n; i++){
            t[s[i]] = d[i];
        }
        d.swap(t);
        cnt++;
    }
    cout << cnt << endl;

문제 이해가 좀 걸렸는데,

처음 카드: 0 1 2 3 4 5 6 7 8
P 순열  : 2 1 1 0 1 0 2 2 0

플레이어0: 3, 5, 8
플레이어1: 1, 2, 4
플레이어2: 0, 6, 7 을 받아야 함(주는 순서 상관x).

이런 뜻이었다.

    for(int i = 0; i < n; i++){
        int a;
        cin >> a;
        m[a].insert(make_pair(i, 1));
    }

그래서 P를 입력 받을 때, map에 각 플레이어 마다 받아야 하는 카드들을 넣었다.

ori[]에 처음의 카드 세팅, 즉 0, 1, 2, ..., n을 저장해 둔다. 만약 카드를 계속 섞었는데 원본으로 돌아와 버리면, 평생 섞어도 목적을 못이루니 종료한다.

chk() 함수로 현재 덱으로 플레이어들에게 그대로 갈 수 있을 지 확인한다. 인덱스는 i%3으로 0, 1, 2에 접근한다.
</br>

1092: 배

https://www.acmcpc.net/problem/1092

무게 제한이 있는 크레인들로 짐 옮기기

    sort(c, c+n);
    cin >> m;
    for(int i = 0; i < m; i++){
        int bx;
        cin >> bx;
        int j = 0;
        for( ; j < n; j++){
            if( bx <= c[j] ){
                bxs[j]++;
                break;
            }
        }
        if( j == n ){
            cout << -1 << endl;
            return 0;
        }
    }
    int sz = m, t = 0;
    while( 1 ){
        for(int i = n-1; i >= 0; i--){
            for(int j = i; j >= 0; j--){
                if( bxs[j] ){
                    bxs[j]--;
                    sz--;
                    break;
                }
            }
            if( sz == 0 ) break;
        }
        t++;
        if( sz == 0 ) break;
    }
    cout << t << endl;

크레인의 무게를 오름차순으로 정렬하고, bxs[]에 해당 크레인이 옮길 수 있는 짐들의 수를 저장했다.

ex)
크레인: 1, 2, 4
짐    : 1, 1, 3, 3
bxs   : 2, 0, 2

그 다음에, 무거운 걸 들 수 있는 크레인부터 무거운 짐을 옮겨 없앤다. 만약 한 바퀴 다 돌았다면 1분 지난 것이고, 짐을 다 옮기면 종료한다.
</br>

1107: 리모컨

https://www.acmcpc.net/problem/1107

리모컨 버튼이 몇 개 고장났을 때 최소로 버튼 눌러서 채널 옮기기

bool chk(int k){
    if( k < 0 ) return false;
    if( k == 0 && broken[k] ) return false;
    while( k ){
        if( broken[k%10] ) return false;
        k /= 10;
    }
    return true;
}

// int main()
    if( n == 100 ){
        cout << 0 << endl;
        return 0;
    }
    int ans = abs(n - 100);
    if( chk(n) ) ans = min(ans, (int)(to_string(n).size()));
    int cnt = 1;
    while( n+cnt <= 1000001 || n-cnt >= 0 ){
        if( chk(n-cnt) ){
            cnt += to_string(n-cnt).size();
            break;
        }
        if( chk(n+cnt) ){
            cnt += to_string(n+cnt).size();
            break;
        }
        cnt++;
    }
    cout << min(ans, cnt) << endl;

어떻게 할까 고민했는데

  1. 처음 100에서 움직이는 수
  2. 바로 그 채널로 움직일 수 있는 지 확인
  3. 목표 채널에서 +c, -c하며 가능한 지 확인(-c의 경우 +c보다 자리수가 적을 가능성이 있으므로 먼저 체크)
    은근 음수 처리랑 고려할 게 많았다
    </br>

현재 143문제를 풀고 학교 랭킹 130등이다
지금 탑 100에 들려면 190문제는 풀어야 한다 갈 길이 머네
</br>

댓글남기기