백준: Class 3 ② - 2667, 5430, 5525

2 분 소요


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

2667: 단지번호붙이기

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

void func(int x, int y){
    d++;
    visited[x][y] = d;
    for(int i = 0; i < 4; i++){
        int nx = x + dx[i];
        int ny = y + dy[i];
        if( visited[nx][ny] == 0 && mmap[nx][ny] == 1 ){
            func(nx, ny);
        }
    }
}

// in main()
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if( visited[i][j] == 0 && mmap[i][j] == 1 ){
                d = 0;
                func(i, j);
                v.push_back(d);
            }
        }
    }
    sort(v.begin(), v.end());
    cout << v.size() << '\n';
    for(int i = 0; i < v.size(); i++){
        cout << v[i] << '\n';
    }

자꾸 왜 틀리지 했는데 마지막 출력에 소팅을 안 해서 그랬다ㅜ
dfs로 방문하지 않았는데 1이면 쭉 들어가서 탐색하고, 그 깊이를 벡터에 저장한다.
벡터의 사이즈가 곧 총 단지 수이고, 각 단지마다 집의 수를 출력한다.
</br>

5430: AC

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

    while( t-- ){
        string s;
        cin >> s;
        int n;
        cin >> n;
        string a;
        cin >> a;

        deque<int> dq;
        for(int i = 1; i < a.size()-1; i++){
            if( a[i] == ',' ) continue;
            int k = a[i++]-'0';
            while( a[i] != ',' && i < a.size()-1 ){
                k *= 10;
                k += a[i++]-'0';
            }
            dq.push_back(k);
        }

        bool error = false;
        bool rev = false;
        for(int i = 0; i < s.size(); i++){
            if( s[i] == 'R' ){
                rev = !rev;
            }
            else if ( s[i] == 'D' ){
                if( dq.size() ){
                    if( rev ) dq.pop_back();
                    else dq.pop_front();
                }
                else error = true;
            }
        }

        if( error ) cout << "error\n";
        else if( dq.size() == 0 ) cout << "[]\n";
        else{
            cout << '[';
            if( rev ){
                while( dq.size() > 1 ){
                    cout << dq.back() << ",";
                    dq.pop_back();
                }
            }
            else{
                while( dq.size() > 1 ){
                    cout << dq.front() << ",";
                    dq.pop_front();
                }
            }
            cout << dq.front() << "]\n";

        }
    }

문자열로 들어오는 배열 파싱, 명령어 처리, 출력으로 나뉘겠다
명령어 처리할 때 뒤집으라고 진짜 뒤집었더니 시간 초과 난다…
deque로 지금 뒤집은 상태인지 아닌지만 체크해서 pop해주자
</br>

5525: IOIOI

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

방법 1.

    string IOI = "";
    for(int i = 0; i < n; i++){
        IOI.append(1, 'I');
        IOI.append(1, 'O');
    }
    IOI.append(1, 'I');

    string s;
    cin >> s;

    int cnt = 0;
    for(int i = 0; i <= s.size()-IOI.size(); i++){
        if( s[i] == 'O' ) continue;
        int j = 0;
        for( ; j < IOI.size(); j++){
            if( s[i+j] != IOI[j] ) break;
        }
        if( j == IOI.size() ) cnt++;
    }

    cout << cnt << endl;

처음에 IOI 문자열을 만들어서 맞대 보는 식으로 했는데, 50점 받았다.
</br>

방법 2.

    int cnt = 0;
    for(int i = 0; i < s.size()-1; i++){
        if( s[i] == 'O' ) continue;
        int c = 0;
        while( i+1 < s.size() ){
            if( s[i] == s[i+1] ){
                if( s[i] == 'O' ){
                    c--;
                }
                else{
                    c++;
                }
                break;
            }
            c++;
            i++;
        }
        if( c/2 - n + 1 > 0 ) cnt += c/2 - n + 1;
    }
    cout << cnt << endl;

m <= 1000000 이므로 이중 포문을 돌면 시간 초과가 나는 거였다!
위 코드 제출하면서 쓸데없는 계산 중복으로 한다 싶기는 했는데…

ex) IOIOIOIOI	4(4+1개의 I, 4개의 O)
1:  IOI
      IOI
        IOI
          IOI   4

2:  IOIOI
      IOIOI
        IOIOI	3

3:   IOIOIOI
      IOIOIOI	2

4:   IOIOIOIOI	1

그래서 생각해 보니, IOIOI…를 찾을 수 있을 만큼 길게 찾고 넘기면 되겠더라.
위처럼, 문자열에서 찾은 IOIOI…의 길이가 4라면, n이 1이면 4번, 2면 3번, 이런 식으로 (4-n+1)개 찾을 수 있다.

ex) n = 1,
OOIOIOIOIIOII(백준 예제 1)

  IOIOIOI     > (3-1+1) = 3개
         IOI  > (1-1+1) = 1개
총 4개


</br>


클래스 문제 풀이가 더 재밌는 것 같다
문제 난이도도 섞여 있고
</br>

댓글남기기