ZOJ4027 Sequence Swapping 線性DP
阿新 • • 發佈:2018-12-17
給定一個括號序列,僅有'()'時左右括號可以相互交換,每個括號都有自己的價值a[i],每次交換費用為a[i]*a[i+1];
求最高的費用
每個‘(’括號只能與右邊相鄰的‘)’交換位置,表示第i個左括號到達j位置的最大費用
等於第i個左括號到達位置j的費用+位置j右邊的最大的
#include<bits/stdc++.h> using namespace std; const int MAX=1e3+5; int t,n,a[MAX],b[MAX],cnt; char s[MAX]; long long dp[MAX][MAX]; int main() { scanf("%d",&t); while(t--) { cnt=0;memset(dp,0,sizeof(dp)); scanf("%d",&n);scanf("%s",s+1); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=n;++i) if(s[i]=='(') b[cnt++]=i;--cnt; for(int i=b[cnt]+1;i<=n;++i) dp[cnt][i]=dp[cnt][i-1]+a[b[cnt]]*a[i]; for(int i=n-1;i>=b[cnt];--i) dp[cnt][i]=max(dp[cnt][i],dp[cnt][i+1]); for(int i=b[cnt];i<=n-1;++i) a[i]=a[i+1]; for(int i=cnt-1;i>=0;--i) { for(int j=b[i]+1;j<=n-cnt+i;++j) dp[i][j]=dp[i][j-1]+a[b[i]]*a[j]; for(int j=b[i];j<b[i+1];++j) dp[i][j]+=dp[i+1][b[i+1]]; for(int j=b[i+1];j<=n-cnt+i;++j) dp[i][j]+=dp[i+1][j+1]; for(int j=n-cnt+i-1;j>=b[i];--j) dp[i][j]=max(dp[i][j],dp[i][j+1]); for(int j=b[i];j<=n-cnt+i-1;++j) a[j]=a[j+1]; } printf("%lld\n",dp[0][b[0]]); } return 0; }