【DP】ZOJ - 4027 - Sequence Swapping

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/82889808

题目链接<https://cn.vjudge.net/problem/ZOJ-4027>


题意:

 有一串小括号组成的字符串,每个括号都有一定的价值。如果把某一个左括号与它右边相邻的右括号交换,可以获得两者价值的乘积。问价值最高能获得多少。


题解:

对于每一个左括号,它都可以跟它后面的右括号进行交换。假设第i个左括号要跟第j个右括号进行交换,那么这第j个右括号必须提上来,即ij之间的所有左括号必须与j进行过交换,而这些括号与j之后的括号是否交换并不关心,对于答案来说只需要取个最大值即可。

从右往左扫,专门开一个数组存储已经扫到的右括号。每扫到一个左括号,就枚举它与每一个右括号匹配的情况。

开一个dp[j]数组,存储这一次把第j个括号提上来的最大价值。

开一个maxn[j]数组,存储上一次把第j个括号提上来的最大价值。


#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const ll N=1e3+7;
char s[N];
ll a[N],tp[N],maxn[N],dp[N];
int main(){
    ll lo,hi,t,n;
    scanf("%lld",&t);
    while(t--){
        memset(maxn,0,sizeof(maxn));
        memset(tp,0,sizeof(tp));
        ll ans=0;
        scanf("%lld",&n);
        scanf("%s",s+1);
        for(ll i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        hi=N-1;lo=hi+1;//lo,hi表示右括号数组的范围
        for(ll i=n;i>=1;i--){
            memset(dp,0,sizeof(dp));
            if(s[i]==')')
                tp[--lo]=a[i];
            else{
                ll tmp=0;
                for(ll j=lo-1;j<=hi;j++){//lo-1是不跟任何一个右括号匹配的情况
                    tmp+=a[i]*tp[j];
                    dp[j]=maxn[j]+tmp;
                    ans=max(ans,dp[j]);
                }
                maxn[hi]=dp[hi];
                for(ll j=hi-1;j>=0;j--)
                    maxn[j]=max(dp[j],maxn[j+1]);
            }
        }
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/82889808
今日推荐