【DP】ZOJ - 4027 - Sequence Swapping
阿新 • • 發佈:2018-11-10
題目連結<https://cn.vjudge.net/problem/ZOJ-4027>
題意:
有一串小括號組成的字串,每個括號都有一定的價值。如果把某一個左括號與它右邊相鄰的右括號交換,可以獲得兩者價值的乘積。問價值最高能獲得多少。
題解:
對於每一個左括號,它都可以跟它後面的右括號進行交換。假設第個左括號要跟第個右括號進行交換,那麼這第個右括號必須提上來,即與之間的所有左括號必須與進行過交換,而這些括號與之後的括號是否交換並不關心,對於答案來說只需要取個最大值即可。
從右往左掃,專門開一個數組儲存已經掃到的右括號。每掃到一個左括號,就列舉它與每一個右括號匹配的情況。
開一個陣列,儲存這一次把第個括號提上來的最大價值。
開一個陣列,儲存上一次把第個括號提上來的最大價值。
#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); } }