본문으로 바로가기

p.62 Best Cow Line (POJ 3617) - Greedy Algorithm

http://poj.org/problem?id=3617


이 문제는 노란책에서 기초적이면서도 처음 접하면 어려운 문제라고 생각한다.

문제는 다음과 같다.

어떤 문자열이 주어지면 앞이나 뒤에서 문자 하나를 빼서 새로운 문자열을 구성하는데,

이 때 새롭게 만들어지는 문자열이 사전순으로 가장 앞에 있도록 만들려고 한다.


그냥 앞뒤 두 문자 보고 사전순으로 앞에 있는 문자를 가져다 쓰면 될 것 같지만,

앞뒤 두 문자가 같을 때에는 문제가 생긴다.

맨 앞에 있는 문자를 s[b], 맨 뒤에 있는 문자를 s[e]라고 하면,


s[b], s[b+1], s[e]

s[e], s[e-1], s[b]

순서로 만들거나


s[b], s[e], s[b+1]

s[b], s[e], s[e-1]

s[e], s[b], s[b+1]

s[e], s[b], s[e-1]

순서로 만들 수 있을 것이다.


그런데, 여기서 s[b]==s[e]인 경우만 s[b+1]과 s[e-1]에 대해서 조사하므로

s[b]를 C라 하면,

C, s[b+1], C

C, s[e-1], C

C, C, s[b+1]

C, C, s[e-1]

중에 하나가 될 것이다.


그럼 C하나는 반드시 써야한다는 결론이 나오고

그 다음의 오는 문자가 s[b+1], s[e-1], C중 하나여야 한다.

여기서 세 문자를 모두 비교하지 않아도 되는데, s[b+1], s[e-1] 두 문자만 비교하고 C는 고려하지 않아도 된다.

왜냐하면 s[b+1]<s[e-1]인 경우 s[b]를 써야하므로 s[b++]을 화면에 출력한다.

그 다음 반복문을 보면 s[b]와 s[e]를 자연스럽게 비교하게 된다. (여기서 b는 1 증가된 상태)

이는 b를 증가시켜주기 전의 s[b+1]값과 C를 비교하는 것과 같다.

또한, s[b+1]<s[e-1]이라면 s[b+1]이 무조건 먼저 나와야 한다.

그러니까 이탤릭체로 쓴 부분에서 s[e-1]을 고려하지 않아도 된다.


사실 이렇게 이해하는게 맞나 싶긴한데 ㅠ 쉽게 생각할 수 있는 방법은 잘 모르겠다.

아무튼 논리는 맞으니까...

조금 다시 정리를 해보자면,

결국 s[b]==s[e]이면 s[b+1]과 s[e-1]을 비교하면 되고, 이 마저도 같으면 s[b+2]와 s[e-2]를 비교하면 된다.

중간에 s[b+i]와 s[e-i]중 b+i쪽이 사전순으로 앞선다면, 현재 턴에서 s[b]를 먼저 써야 한다는 결론이 나온다.


N제한이 2000이므로 에 충분히 돌아간다. ^^


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
string s, rs;
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> s;
    int b=0, e=s.size()-1;
    while(b<=e) {
        bool left = false;
        for(int i=0; b+i<=e; i++) {
            if(s[b+i]<s[e-i]) {
                left=true;
                break;
            } else if(s[b+i]>s[e-i]) {
                left=false;
                break;
            }
        }
        if(left) putchar(s[b++]);
        else putchar(s[e--]);
    }
    return 0;
}
cs


코드는 위와 같은데, POJ에서 80번째 문자마다 개행문자 넣으라는 걸 만들지 않았다.

(책에 있는 코드와 완전히 같다.)


사실 난 이게 생각이 잘 안된다. ㅠ

딱 코포 C번 느낌이다.

기본적인 문제인데.. 뭔가 생각 정리를 할 수가 없다.

답을 보면 "아 저거구나~!" 하는데, 더 쉽게 생각하는 방법이 있으면 누가 댓글좀... ㅠ