ZOJ-4027 & 2018浙江省赛-D题 Sequence Swapping

2018浙江省赛-D题 

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4027

题意:

当且仅当sk='('并且s(k+1)=')'时可以交换二者,并且得到两者价值乘积的价值,问最多可以得到多少价值。

思路:

用的dp做法
首先,这道题要求只能左括号和右括号换,这就决定了每个左括号能到达的最右位置,如果这个括号可以被移动到第j个位置,那么他后面的左括号一定都在比他右的位置,
也就是j+1位之后,设dp[i][j]是把第i个左括号移动到j右面(包括j)位中能得到的最大价值
转移方程为:
    dp[i][j]=max(dp[i+1][j+1]+移动到这里能得到的值,dp[i][j+1])(可以直接开始,因为dp[i+1][j+1]一开始是0所以无影响)
而移动到这里所得到的值是(移动的这个左括号的值)*(他交换的右括号的值的和),用前缀和表示前多少个右括号的和,在输入的时候记录它前面有几个右括号,
他所在位减去他右边的左括号就是他右边的右括号的值数量。由此可知:右括号的值的和=前缀和(括号总数量-右边括号)-前缀和(左边的右括号)。

// 18浙江省赛 D, zoj 4027, dp, - Sequence Swapping
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int maxn = 2e4 + 5;
int n;
char s[maxn];
long a[maxn], dp[maxn][maxn];

int main() {
    //freopen("data.txt", "r", stdin);
    int T;
    cin >> T;
    while (T--) {
        cin >> n;
        scanf("%s", s + 1);
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        memset(dp, 0, sizeof(dp)); //初始化
        for (int i = 1; i <= n; i++)//记录能匹配的分数
            if (s[i] == '(') {
                for (int j = i + 1; j <= n; j++) {
                    long res = s[j] == ')' ? a[i] * a[j] : 0;
                    dp[i][j] = dp[i][j - 1] + res;
                }
            }

        for (int i = 1; i <= n; i++) {//动态规划
            long res = 0;
            for (int j = 1; j <= n; j++) {
                res = max(res, dp[i - 1][j]);
                dp[i][j] += res;
            }
        }

        long ans = 0;
        for (int j = 1; j <= n; j++)//找到max,输出
            ans = max(ans, dp[n][j]);
        cout << ans << endl;
    }

    return 0;
}

/*
输入
4
6
)())()
1 3 5 -1 3 2
6
)())()
1 3 5 -100 3 2
3
())
1 -1 -1
3
())
-1 -1 -1

输出
24
21
0
2
*/


--------------------- 
解题思路来源:呆呆萝莉控 
原文:https://blog.csdn.net/qq_40792618/article/details/80145467 

猜你喜欢

转载自blog.csdn.net/qq_38861305/article/details/90114779