1. 程式人生 > >51nod 1476 括號序列的最小代價 (括號題套路+反悔貪心)

51nod 1476 括號序列的最小代價 (括號題套路+反悔貪心)

問號 nod algo strlen 51nod urn pty sum top

題意:給一串只有‘(‘ , ‘)‘ , ‘?‘ 的括號序列,每個?可以變成)或者(,代價分別為bi和ai,求變成合法序列的最小代價

思路:學習自最近的網絡賽&&51nod貪心專題視頻的思想,“反悔”,一般在獲取收益有限制的情況下使用

先按某種“優”的策略貪心,如果不滿足限制條件了,取一個修改後代價盡可能小的狀態修改成滿足條件的狀態,得到新的滿足限制下的最優解

這種貪心常常可以借助優先隊列實現

然後是括號題的套路:把(當做1,把)當做-1,做前綴和

這題中,先當做所有的?都換成右括號,這是顯然的,順推只要前綴和小於0就是不合法,需要“反悔”,優先隊列維護ai和bi的差值,每次取換成左括號最便宜的問號轉換

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<queue>
 6 #define LL long long
 7 #define debug(x) cout << "[" << x << "]" << endl
 8 using namespace std;
 9 
10 const int mx = 50010;
11
char s[mx]; 12 LL a[mx], b[mx]; 13 14 int main(){ 15 priority_queue<LL> q; 16 int sum = 0; 17 LL ans = 0; 18 scanf("%s", s); 19 int len = strlen(s); 20 for (int i = 0; i < len; i++) 21 if (s[i] == ?) scanf("%lld%lld", &a[i], &b[i]); 22 for
(int i = 0; i < len; i++){ 23 if (s[i] == () sum++; 24 else { 25 sum--; 26 if (s[i] == ?) { 27 ans += b[i]; 28 q.push(b[i]-a[i]); 29 } 30 } 31 if (sum < 0){ 32 if (q.empty()){ 33 printf("-1\n"); 34 return 0; 35 } 36 ans -= q.top(); 37 sum += 2; 38 q.pop(); 39 } 40 } 41 if (sum != 0) printf("-1\n"); 42 else printf("%lld\n", ans); 43 return 0; 44 }

51nod 1476 括號序列的最小代價 (括號題套路+反悔貪心)