CF3D Least Cost Bracket Sequence

版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/89737507

D e s c r i p t i o n Description

给定一个由‘(’,’)‘以及’?'构成的字符串

替换第 i i 个括号变成左括号耗费 a i a_i ,变成右括号耗费 b i b_i

现在你要替换一些’?‘,使这个序列变成合法的序列且代价和最小

下面是关于合法序列的定义和性质:

  1. 一个空串是一个合法序列
  2. S S 是一个合法序列,则( S S )也是一个合法序列
  3. A B A,B 都是合法序列,则 A B AB 也是一个合法序列

数据范围:
字符串长度 5 × 1 0 4 0 a i , b i 1 0 6 \leq 5\times 10^4,0\leq a_i,b_i\leq 10^6


S o l u t i o n Solution

这是一道比较简单的贪心题,首先默认所有问号为右括号,当当前的左括号数小于右括号时,则从之前找到代价最小的问号变成的右括号代替即可,正确性显然。

代价最小的这个过程可以用堆,时间复杂度 O ( n l o g n ) O(nlogn)


C o d e Code

#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;int l,n,a,b;
long long ans;
char s[50001];
struct node{int x,id;};
inline bool operator <(const node &x,const node &y){return x.x<y.x;}
priority_queue<node>q;
inline int read()
{
    char c;int f=0,d=1;
    while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
signed main()
{
	scanf("%s",s);
	n=strlen(s);
	for(register int i=0;i<n;i++)
	{
		if(s[i]=='(') {l++;continue;}//l表示当前左右括号的差值
		else
		{
			if(s[i]=='?')
			{
				a=read();b=read();
				q.push((node){b-a,i});//把替换代价放入小根堆
				s[i]=')';
				ans+=b;
			}
			if(--l<0)//替换成右括号,l--
			{
				if(q.empty()) return puts("-1")&0;
				ans-=q.top().x;//减去最小替换代价
				s[q.top().id]='(';
				l+=2;
				q.pop();
			}
		}
	}
	if(l) return puts("-1")&0;
	//注意判断序列本来就不合法的情况,刚开始就是因为这个WA了第48个点
	printf("%I64d\n%s",ans,s);//输出
}

后记——一些想法

注意:以下内容并非本题解法,只是记录原有思路

刚开始想着去 d p dp

f [ i ] [ j ] f[i][j] 表示前i个位置,当前左括号与右括号的差值为j时的最小代价

当第i位是左括号时, f [ i ] [ j ] = f [ i 1 ] [ j + 1 ] f[i][j]=f[i-1][j+1]
当第i位是右括号时, f [ i ] [ j ] = f [ i 1 ] [ j 1 ] f[i][j]=f[i-1][j-1]
当第i为是?时, f [ i ] [ j ] = m i n ( f [ i 1 ] [ j 1 ] + a [ i ] , f [ i 1 ] [ j + 1 ] + b [ i ] ) ] f[i][j]=min(f[i-1][j-1]+a[i],f[i-1][j+1]+b[i])]

扫描二维码关注公众号,回复: 6198891 查看本文章

终点 f [ n ] [ 0 ] f[n][0]

酱紫的时间复杂度和空间复杂度都是 O ( n 2 ) O(n^2) ,不过可以用滚动数组将空间复杂度压缩到 O ( n ) O(n) ,对于时间复杂度,我的想法是记录当前最大的左右括号差值,这样子的最坏时间复杂度是 O ( n 2 ) O(n^2)

不过由于笔者没有想到保存路径的方法, 所以这种想法就被搁置了,如果各位大爷有比较好的想法可以推荐一下呀QWQ

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/89737507