CF 3D Least Cost Bracket Sequence

来源:互联网 发布:webpack搭建php服务器 编辑:程序博客网 时间:2024/05/17 01:25

题目大意:给一个括号序列,其中有一些位置是问号,问号可以变成左括号或右括号,每个问号变成其中一种符号都有代价。求代价最小的合法括号序列的代价以及序列。

题解:这个问题是有后效性的,因为后面的决策不取决于前面的某一个阶段的状态,而是与之所有阶段的状态都有关,不能用dp来解。正解是贪心,先假设所有的问号都是右括号,如果某个位置不合法了,检查前面是否有问号,如果有的话找一个代价最小的进行纠正,否则一定无法构成正确的序列。

#include <bits/stdc++.h>using namespace std;const int maxn = 50100;struct node{    int idx,a,b;    node(int i,int x,int y):idx(i),a(x),b(y){}    node(){}    bool operator<(const node &x)const {        return a-b>x.a-x.b;    }};priority_queue<node> Q;typedef long long ll;int a[maxn],b[maxn];int id[maxn];char str[maxn];int main(){    scanf("%s",str);    int len = strlen(str);    int n = 0;    for(int i = 0;i < len;i++)        if(str[i] == '?'){            str[i] = ')';            id[n++] = i;        }    ll ans = 0;    int cnt = 0;    bool flag = true;    for(int i = 0;i < n;i++) scanf("%d%d",&a[i],&b[i]),ans +=b[i];    for(int i = 0,j = 0;i < len;i++){        if(i == id[j]){            Q.push(node(i,a[j],b[j]));            j++;        }        if(str[i] == '(') cnt++;        if(str[i] == ')') cnt--;        if(cnt < 0){            if(!Q.empty()){                node tmp = Q.top();                Q.pop();                ans += tmp.a-tmp.b;                cnt += 2;                str[tmp.idx] = '(';            }            else{                flag = false;                break;            }        }    }    if(cnt>0) flag = false;    if(!flag){        printf("-1\n");        return 0;    }    printf("%I64d\n",ans);    printf("%s\n",str);    return 0;}
0 0