3D(大贪心)

题目链接

题目大意:

给一个序列,序列里面会有左括号、问号、右括号。对于一个‘?’而言,可以将其替换为一个‘(’,也可以替换成一个‘)’,但是都有相应的代价。问:如何替换使得代价最小。前提是替换之后的序列中,括号是匹配的。如果不能替换为一个括号匹配的序列则输出-1。


输入

第一行是序列,序列长度不超过 ,下面mm是'?'的数量)行,每行  个数据,第一个是 '('的代价,第2个是 ')' 的代价。

输出:

第一行输出最小代价,第二行输出替换后的序列。不行输出 

 

解题思路:

题目要求的是求最小的价值,好像只要关于最值的都或多或少的跟贪心有些关系。没有意外,这道题目也是贪心的利用。那么如何贪呢?

为保证最后的代价并且需要符合括号匹配规则,那么我们将所有的?号全部先转化为右括号‘)’,如当前的左右括号不匹配的时候我们就向该下标及之前寻找“?”。然后让其转化为‘(‘即可。贪心的规则是寻找前面可以付出最少代价的’?‘处。也就是说b - a 最大的情况。为什么呢?

因为我们要在括号匹配的前提下来求代价的最低值,如果右括号确定的话,那样就会有唯一的贪心方案去确定(最优)左括号的位置。假设我们先将其转化为左括号的话,我们无法保证他可以转化为右括号而保证其最优。所以确定右括号即可。那为什么是b - a 呢?因为我们一开始加的是b,而后我们需要将其转化为a,那么他的计算表达式为ans = ans - (b - a) ,也就是 ans = ans - b + a,我们的目的是保证其最小化,显然(b - a)越大那么ans就会越小了,这样我们就可以用一个优先队列来维护了。

当然,他还会存在无法匹配的情况

  1. 比如字符串的长度为奇数的时候是怎么也不可能匹配成功的,
  2. 还有最后有左括号剩余也是不可以的,
  3. 还有一种就是在当前位置右括号大于左括号了,并且此位置及之前没有?出现,这也是不可以匹配成功的。

题目不错。

AC代码:

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = (j); i <= (k); ++i)
#define R(i, j, k) for(int i = (j); i >= (k); --i)
#define ll long long
#define sz(a) ((int) (a).size())
#define vi vector< int >
#define me(a, x) memset(a, x, sizeof(a))
#define ull unsigned long long

using namespace std;

string s;
typedef pair<int, int> PII;
ll ans;
priority_queue<PII> q; 
void solved()
{
	cin >> s;
	if (s.size() & 1) 
	{
		cout << "-1";
		return ;
	}
	int cnt = 0; //标记左括号
	
	for (int i = 0; i < s.size(); i ++ )
	{
		 
		if (s[i] == '(') cnt ++;
		else if (s[i] == ')') cnt --;
		else //先将?全部转化为 右括号, 
		{
			int a, b;
			cin >> a >> b;
			s[i] = ')';
			cnt --;
			q.push({b - a, i});
			ans += b;
		} 
		
		if (cnt < 0 && q.empty()) //在该处之前不能完成匹配,直接跳出 
		{
			cout << "\-1";
			return;
		}
		
		if (cnt < 0) //如果当前匹配不合法,据将前面的?转化为(
		{
			int a = q.top().first, b = q.top().second;
			q.pop();
			ans -= a;
			cnt += 2;
			s[b] = '(';
		} 	
	} 
	
	if (cnt) cout << "-1";
	else cout << ans << '\n' << s;
	
}


int main(){
	ios :: sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	solved();
	return 0;
}

/* stuff you should look for 你应该寻找的东西
 * int overflow, array bounds (int)溢出,数组边界
 * special cases (n=1?) 特殊情况(n=1?)
 * do smth instead of nothing and stay organized 做一些事情而不是什么也不做,保证效率
 * WRITE STUFF DOWN 将东西写下
 * DON'T GET STUCK ON ONE APPROACH 不要在一个地方死磕
 */

 

posted @ 2022-11-18 11:46  Luli&  阅读(25)  评论(0编辑  收藏  举报