zoukankan      html  css  js  c++  java
  • Wannafly Winter Camp 2020 Day 6I 变大!

    给定一个序列,可以执行 (k) 次操作,每次选择连续的三个位置,将他们都变成他们的最大值,最大化 (sum a_i)

    需要对每一个 (k=i) 输出答案

    (n leq 50, a_i leq 20),数据组数 (leq 100)

    Solution

    我们考虑将这些数分段,每段刷成区间内的最大值,那么很显然就可以 DP 了

    (f[i][j]) 表示搞定了前 (i) 个数,操作了 (j) 次,则转移方程

    [f[i][j]=max_k (f[k][j-frac{i-k}{2}]+m[k+1][i]cdot (i-k)) ]

    其中 (m[l][r]) 表示 ([l,r]) 这段区间的最大值,可以暴力预处理得到

    总体时间复杂度 (O(Tn^3))

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 105;
    int t,n,a[N],f[N][N],m[N][N];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--) {
            cin>>n;
            for(int i=1;i<=n;i++) cin>>a[i];
            memset(f,0,sizeof f);
            memset(m,0,sizeof m);
            for(int i=1;i<=n;i++) {
                for(int j=i;j<=n;j++) {
                    for(int k=i;k<=j;k++) {
                        m[i][j]=max(m[i][j],a[k]);
                    }
                }
            }
            memset(f,-0x3f,sizeof f);
            f[0][0]=1;
            for(int i=1;i<=n;i++) {
                for(int j=0;j<=n;j++) {
                    if(j>0) f[i][j]=f[i][j-1];
                    for(int k=0;k<i;k++) {
                        if(j>=(i-k)/2 && k!=i-2)
                            f[i][j]=max(f[i][j],
                                f[k][j-(i-k)/2]+m[k+1][i]*(i-k));
                    }
                }
            }
            for(int i=1;i<=n;i++) {
                cout<<f[n][i]-1<<(i==n?"
    ":" ");
            }
        }
    }
    
    
  • 相关阅读:
    第七章11
    第七章10
    第七章9
    第七章8
    第七章7
    第七章6
    第七章5
    第七章例7-13
    第七章例7-12
    第七章例7-11
  • 原文地址:https://www.cnblogs.com/mollnn/p/12367442.html
Copyright © 2011-2022 走看看