zoukankan      html  css  js  c++  java
  • bzoj4897 [Thu Summer Camp2016]成绩单

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4897

    【题解】

    第一次看这题想的是f[l,r]的区间dp发现仅记录这两个好像不能转移啊

    会出现abaca这种情况,也就是拿走的段在原序列中不连续。

    考虑为什么会出现这个情况,肯定是这三个a里的元素十分集中,我们才会留着等合并后取。

    我们离散值域,记f[l,r,nl,nr]表示[l,r]区间内,剩下[nl,nr]没拿走的min代价。

    特别的如果nl=nr=0就表示全拿走了。

    那么考虑f[l,r,nl,nr]怎么转移。

    首先转移满足区间性质,也就是可以分割,所以

    f[l,r,nl,nr]=min(f[l,k,nl,nr]+f[k+1,r,nl,nr], f[l,k,nl,nr]+f[k+1,r,0,0], f[l,k,0,0]+f[k+1,r,nl,nr])

    然后考虑f[l,r,0,0]的转移:我要取完这个区间,要么是一次性取完:f[l,r,0,0]=min(f[l,r,0,0], a+b(Max[l..r]-Min[l..r])^2)

    要么是留着[x,y]区间,最后取这个区间:f[l,r,0,0] = min(f[l,r,x,y]+a+b(y-x)^2)

    然后转移就行啦,复杂度O(n^5)

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 50 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, A, B, a[M], w[M];
    ll f[M][M][M][M];
    bool vf[M][M][M][M];
    vector<int> ps;
    
    inline ll dp(int l, int r, int nl, int nr) {
        if(vf[l][r][nl][nr]) return f[l][r][nl][nr];
        vf[l][r][nl][nr] = 1;
        ll ret = 1e18;
        if(nl == 0 && nr == 0) {
            int mx = -1e9, mi = 1e9;
            for (int i=l; i<=r; ++i) mx = max(mx, w[i]), mi = min(mi, w[i]);
            f[l][r][0][0] = A + (ll)B * (ps[mx-1]-ps[mi-1]) * (ps[mx-1]-ps[mi-1]);
            for (int i=1; i<=m; ++i)
                for (int j=i; j<=m; ++j) 
                    ret = min(ret, dp(l, r, i, j) + A + (ll)B * (ps[j-1]-ps[i-1]) * (ps[j-1]-ps[i-1]));
            return f[l][r][0][0] = ret;
        }
        if(l == r) {
            if(nl <= w[l] && w[l] <= nr) ret = 0;
            return f[l][r][nl][nr] = ret;
        }
        for (int k=l; k<r; ++k) {
            ret = min(ret, dp(l, k, nl, nr) + dp(k+1, r, nl, nr));
            ret = min(ret, dp(l, k, nl, nr) + dp(k+1, r, 0, 0));
            ret = min(ret, dp(l, k, 0, 0) + dp(k+1, r, nl, nr));
        }
        return f[l][r][nl][nr] = ret;
    }
    
    int main() {
        cin >> n >> A >> B;
        for (int i=1; i<=n; ++i) {
            scanf("%d", a+i);
            ps.push_back(a[i]);
        }
        sort(ps.begin(), ps.end());
        ps.erase(unique(ps.begin(), ps.end()), ps.end());
        m = ps.size();
        for (int i=1; i<=n; ++i) 
            w[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1;
        cout << dp(1, n, 0, 0);
        return 0;
    }
    View Code
  • 相关阅读:
    oarcle 提取数字函数
    通用XML操作类(微型本地xml数据库)
    linux内核模块Makefile的解析
    开源的许可证GPL、LGPL、BSD、Apache 2.0的通俗解释
    弹性布局
    CSS基础知识
    HTML5基本标签
    VS2008开发Windows Mobile6环境搭建及模拟器联网问题图解
    .Silverlight Binding (One Time,One Way,Two Way)
    WCF Service中HttpContext.Current为null的解决办法
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj4897.html
Copyright © 2011-2022 走看看