• The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple / ZOJ4027 Sequence Swapping dp递推


    Sequence Swapping

    题意:
    给出长度为 n 的一组括号,每个括号有一个权值。操作:选择一对相邻的左括号和右括号,且左括号在左,交换这两个括号,得到价值为这两个括号权值的乘积。
    现在要你按这个操作,问最后的价值和最大可能是多少?
    tags:
    明显 dp,但很难想到。。
    dp[i][j] 表示当前在第 i 个右括号,且第 i 个右括号与它前面 j 个左括号交换后的最大价值和。
    我们可以预处理出第 i 个右括号与第 i-1 个右括号之间有 k 个左括号,那么转移为:

    • if(j <= k) dp[i][j] = max({dp[i-1][0], dp[i-1][1]......}) + sum(第 i 个右括号左边 j 个左括号的和) * value[i] ;
    • else dp[i][j] = max({dp[i-1][j-k], dp[i-1][j-k+1].....}) + sum(第 i 个右括号左边 j-k 个左括号的和) * value[i] ;
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 1005;
    
    int T, n;
    char s[N];
    ll  val[N], cnt1[N], cnt2[N], sum[N][N], cntL, cntR;
    ll  dp[N][N], vis[N], mx[N][N];
    void Init() {
        cntL= cntR = 0;
        mes(cnt1, 0);  mes(cnt2, 0);
        mes(sum, 0);
        rep(i,1,N-1) rep(j,0,N-1) mx[i][j] = -1e18;
    }
    int main()
    {
        scanf("%d", &T);
        while(T--)
        {
            Init();
            scanf("%d%s", &n, s+1);
            rep(i,1,n)
            {
                scanf("%lld", &val[i]);
                if(s[i]==')') {
                    ++cntR;
                    vis[i] = cntR;
                    int num = 0;
                    per(j,i-1,1) if(s[j]=='(') {
                        ++num;
                        sum[cntR][num] = sum[cntR][num-1]+val[j];
                    }
                    ll  tmp = 0;
                    per(j,i-1,1) {
                        if(s[j]==')') break;
                        else  ++tmp;
                    }
                    cnt2[cntR] = cnt2[cntR-1]+tmp;
                    cnt1[cntR] = tmp;
                }
            }
    
            ll  ans = 0;
            rep(i,1,n) if(s[i]==')')
            {
                int id = vis[i];
                per(j,cnt2[id],0) {
                    if(j<=cnt1[id]) {
                        dp[id][j] = mx[id-1][0] + sum[id][j]*val[i];
                    }
                    else {
                        dp[id][j] = mx[id-1][j-cnt1[id]] + sum[id][j]*val[i];
                    }
                    mx[id][j] = max(mx[id][j+1], dp[id][j]);
                    if(id==cntR) ans = max(ans, dp[id][j]);
                }
            }
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
    
  • 相关阅读:
    4-8 求二叉树高度 (20分)
    汉诺塔的递归和非递归实现
    5-18 银行业务队列简单模拟 (25分)
    ACM 刷题小技巧【转】
    5-21 求前缀表达式的值(25分)
    5-20 表达式转换 (25分)
    约瑟夫环----循环链表问题
    关于埃拉托色尼筛选法的整理(质数问题)
    编码---隐藏在计算机软硬件背后的语言
    内排序和外排序扫盲
  • 原文地址:https://www.cnblogs.com/sbfhy/p/9005028.html
Copyright © 2020-2023  润新知