1. 程式人生 > >ZOJ 4027 Sequence Swapping(DP)題解

ZOJ 4027 Sequence Swapping(DP)題解

題意:一串括號,每個括號代表一個值,當有相鄰括號組成()時,可以交換他們兩個並得到他們值的乘積,問你最大能得到多少

思路:DP題,註定想得掉頭髮。

顯然一個左括號( 的最遠交換距離由他右邊的左括號的最終位置決定,那麼我們可以從右邊開始做。我們用dp[i][j]表示第i個左括號交換到第j個位置後,他和他後面左括號所能得到的最大值。顯然,dp[i][j] = i交換得到的值 + 後面左括號產生的最大值。而後面左括號能產生的最大值顯然就是max(dp[i+1][k])其中j <= k <= n。

程式碼:

#include<cstdio>
#include<cstring>
#include
<algorithm> using namespace std; typedef long long ll; const int maxn = 1e3 + 10; const int INF = 0x3f3f3f3f; char s[maxn]; ll v[maxn], n, Max, pos[maxn], sum[maxn]; ///Max[i]定義為後面的交換到i的最大值 ll dp[maxn][maxn]; ///第i個放在j位置得到的最大值 int main(){ int t, cnt; scanf("%d", &t); while
(t--){ cnt = 0; scanf("%lld", &n); scanf("%s", s + 1); sum[0] = 0; for(int i = 1; i <= n; i++){ scanf("%lld", &v[i]); if(s[i] == ')') sum[i] = sum[i - 1] + v[i]; else pos[++cnt] = i, sum[i] = sum[i - 1]; } memset(dp,
0, sizeof(dp)); for(int i = cnt; i >= 1; i--){ int u = pos[i]; Max = -INF; for(int j = n; j >= u; j--){ Max = max(Max, dp[i + 1][j]); dp[i][j] = (sum[j] - sum[u - 1]) * v[u] + Max; } } ll ans = -INF; for(int i = 1; i <= n; i++) ans = max(ans, dp[1][i]); printf("%lld\n", ans); } return 0; }