题目链接:zoj 4027
一直在准备考试以及麻痹自己的学习,所以完美的避开了整个四月,唉
输入s之后给将左右括号分别存放在c,d两个数组中,并给每个左右括号编号,dp【i】【j】代表将第i个左括号放到第j个右括号之后得到的分数(此时序号比 i 大的所有左括号都已经放置完毕,并且dp【i】【j】包含了这些值)
maxx=max(dp【k】);(k>=j)
dp[i][j]=(d[j]-d[i])*c[i]+maxx;(d【i】是只计算右括号的前缀和)
找前面左括号最大值的时候不妨从右到左遍历,这样每次用O(1)时间更新就行了
之前把maxx的初始值设为0了,真的坑,wa了20多发!!
智商是硬伤。。。
#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define sqr(a) (a)*(a)
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,n,m) for(int i=n;i>=m;i--)
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
LL dp[1010][1010];
int a[1010];
int b[1010];
int tt[1010];
int c[1010];
int d[1010];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
lan(a,0);
lan(b,0);
lan(tt,0);
lan(c,0);
lan(d,0);
lan(dp,0);
int n;
scanf("%d",&n);
char s[1010];
getchar();
scanf("%s",s);
For(i,1,n)
scanf("%d",&b[i]);
int p=0,q=0;
int tem=0;
For(i,0,n-1)
{
if(s[i]=='(')
{
a[i+1]=0;
c[++p]=b[i+1],tt[p]=tem;
}
else
{
d[q+1]=d[q]+b[i+1];
q++;
tem++;
a[i+1]=1;
}
}
LL ans=0;
Dor(i,p,1)
{
int temp=tt[i];
LL maxx=-inf;
Dor(j,q,temp)
{
maxx=max(maxx,dp[i+1][j]);
dp[i][j]=(d[j]-d[temp])*c[i]+maxx;
ans=max(ans,dp[i][j]);
}
}
printf("%lld\n",ans);
}
return 0;
}