題目大意:給一個括號序列,其中有一些位置是問號,問號可以變成左括號或右括號,每個問號變成其中一種符號都有代價。求代價最小的合法括號序列的代價以及序列。
題解:這個問題是有後效性的,因爲後面的決策不取決於前面的某一個階段的狀態,而是與之所有階段的狀態都有關,不能用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;
}