题目大意:给一个括号序列,其中有一些位置是问号,问号可以变成左括号或右括号,每个问号变成其中一种符号都有代价。求代价最小的合法括号序列的代价以及序列。
题解:这个问题是有后效性的,因为后面的决策不取决于前面的某一个阶段的状态,而是与之所有阶段的状态都有关,不能用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;
}