티스토리 뷰

[Codeforces 1153C] Serval and Parenthesis Sequence - 1600


문제 설명 : 

(,),? 로 이루어진 문자열이 주어진다. 이 중에서 ?로 채워진 칸은 임의로 ( 또는 ) 로 바꿀 수 있다. 이때 strict prefix(길이가 0이거나 n일 때는 제외하는 prefix)는 절대로 올바른 괄호열이 되어서는 안되게하면서, 전체 문자열은 반드시 올바른 괄호열이 되어야 한다. 이 두 조건은 만족하는 문자열을 구하는 문제이다.


풀이 : 

처음에는 엄청나게 오답을 꼬라박은 문제이다. 처음 풀이는 여는 괄호 '(' 을 +1, 닫는 괄호 ')'를 -1, 이것들의 누적합을 sum이라고 했을 때 sum이 1이나 2 사이에서만 움직이도록 통제하였다. 하지만 이 풀이는 " ???))) "같은 문자열을 처리할 수 없다(정답을 " ())))) " 라고 낼 것이다).

정답은 바로 전체 문자열에서 앞부분에는 여는 괄호를 최대한 많이 배정해서 sum을 높인 다음에, 반환점을 돈 후에는 다시 닫는 괄호만 배정해서 sum을 낮춘다. 그래서 최종 마지막 글자에 도달했을 때는 sum이 0이 되도록 하는 것이다. 이 방법으로 푼다면 처음 생각했던 풀이와 달리 중간에서 sum이 0이 되거나 끝에 0을 못 만드는 일을 피할 수 있다. 그래서 처음에 '?'의 개수를 세면서 최대로 배정할 수 있는 괄호의 개수가 몇 개인지 계산해야한다.


주의할 점 : 

예외처리를 해야할 부분이 꽤 있다. 일단 글자수의 길이가 반드시 짝수어야 한다. 홀수라면 올바른 괄호열 자체를 만들 수가 없기 때문이다. 그리고 괄호열을 다 만든 다음에 검증할 때도 마지막 글자에 도달하기 전에 0이 되어서도 안된다.


배운 점 : 

문자열 앞부분에는 (만 배정하고, 뒷부분에는 )만 배정함으로써 서로 충돌의 가능성을 없앤 방법이다.


코드 :

 

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<functional>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<assert.h>
#include<stdlib.h>
#include<stack>
using namespace std;
/*********************Contest Template***********************/
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
#define FASTIO ios_base::sync_with_stdio(false);cin.tie(0);
struct S{
    int a,b; S(){}S(int _a,int _b)
    { a=_a; b=_b; }
    const bool operator<(const S &o) const{
        return a<o.a;}
};
priority_queue<int,vector<int>,greater<int>> mpq;
const int SPACE=0,NL=1;  string exm;
inline void showAll(vector<int> &v,int sep){ //0=space,1="\n"
    for(int &here:v) printf("%d%c",here,(sep)?'\n':' '); }
inline void exf(void){ cout<<exm<<"\n"; exit(0); }
/*********************Contest Template***********************/
const int SIZE= 300009;
char str[SIZE];
 
int main(){
    int n;    scanf("%d",&n);
    scanf("%s",str+1);
 
    exm=":(";
 
    if(n&1) exf();
    int sum=0,not_filled=0;
    for(int i=1 ; i<=n ; i++){
        if(str[i]=='?') not_filled++;
        else if(str[i]=='(') sum++;
        else sum--;
    }
    int op,cl;
    op=(not_filled-sum)/2,cl=not_filled-op;    
 
    for(int i=1 ; i<=n ; i++){
        if(str[i]=='?' && op>0){
            op--;
            str[i]='(';
        }
        else if(str[i]=='?')
            str[i]=')';
    }
 
    int check=0;
    for(int i=1 ; i<=n ; i++){
        check+=(str[i]=='(')?1:-1;
        if(check<0 ||(i<&& check==0)) exf();
    }
    if(check!=0) exf();
    else printf("%s",str+1);
    return 0;
}
 
cs


'Problem Solving > Greedy' 카테고리의 다른 글

[CF 1136D] Nastya Is Buying Lunch  (0) 2019.07.06
[CF 898D] Alarm Clock  (0) 2019.06.28
[Codeforces 950C] Zebras  (0) 2019.05.21
[Codeforces 1036D] Vasya and Arrays  (0) 2019.04.24
[Codeforces 1066B] Heaters  (0) 2019.02.18
댓글