[THUSC2016]成绩单 [区间dp]

简单区间dp。

考虑 \(f_{i,j,mn,mx}\)表示 \(i,j\) 区间的最大值为 \(mx\),最小值为 \(mn\) 的最小花费,\(g_{i,j}\) 为删掉 \([i,j]\) 的最小花费。目标答案:\(g_{1,n}\)

我们容易发现这个状态可以由区间 \([L,R-1]\) 和 \([R,R]\) 合并起来,即加入一个 \(v_r\) ,第一个转移方程 \(f_{i,j,\min(mn,v_r),\max(mx,v_r)} = \min \{f_{i,j-1,mn,mx}\}\)

我们还可以枚举断点 \(k\) , 把区间分成 \([L,k]\) 和 \([k+1,r]\)
\(f_{i,j,mn,mx} = \min (f_{i,j,mn,mx},f_{i,k,mn,mx} + g_{k+1,r})\)

更新 \(g_{l,r}\)

枚举 \(f_{l,r,mn,mx}\) 最小值为 \(mn\),最小值为 \(mx\),模拟删去过程就好了。

\(g_{l,r} = \min(f_{l,r,mn,mx}+a+b(mx-mn)^2)\)

这题没了

// powered by c++11
// by Isaunoya
#include<bits/stdc++.h>
#define rep(i , x , y) for(register int i = (x) ; i <= (y) ; ++ i)
#define Rep(i , x , y) for(register int i = (x) ; i >= (y) ; -- i)
using namespace std ;
using db = double ;
using ll = long long ;
using uint = unsigned int ;
#define int long long
using pii = pair < int , int > ;
#define ve vector
#define Tp template
#define all(v) v.begin() , v.end()
#define sz(v) ((int)v.size())
#define pb emplace_back
#define fir first
#define sec second
// the cmin && cmax
Tp < class T > void cmax(T & x , const T & y) {
        if(x < y) x = y ;
}
Tp < class T > void cmin(T & x , const T & y) {
        if(x > y) x = y ;
}
// sort , unique , reverse
Tp < class T > void sort(ve < T > & v) {
        sort(all(v)) ;
}
Tp < class T > void unique(ve < T > & v) {
        sort(all(v)) ;
        v.erase(unique(all(v)) , v.end()) ;
}
Tp < class T > void reverse(ve < T > & v) {
        reverse(all(v)) ;
}
const int SZ = 0x191981 ;
struct FILEIN {
    ~ FILEIN () {} char qwq[SZ] , * S = qwq , * T = qwq , ch ;
    char GETC() {
        return (S == T) && (T = (S = qwq) + fread(qwq , 1 , SZ , stdin) , S == T) ? EOF : * S ++ ;
    }
    FILEIN & operator >> (char & c) {
        while(isspace(c = GETC())) ;
        return * this ;
    }
    FILEIN & operator >> (string & s) {
        while(isspace(ch = GETC())) ;
        s = ch ;
        while(! isspace(ch = GETC())) s += ch ;
        return * this ;
    }
    Tp < class T > void read(T & x) {
            bool sign = 1 ;
            while((ch = GETC()) < 0x30) if(ch == 0x2d) sign = 0 ;
            x = (ch ^ 0x30) ;
            while((ch = GETC()) > 0x2f) x = x * 0xa + (ch ^ 0x30) ;
            x = sign ? x : -x ;
    }
    FILEIN & operator >> (int & x) {
        return read(x) , * this ;
    }
    FILEIN & operator >> (signed & x) {
        return read(x) , * this ;
    }
    FILEIN & operator >> (unsigned & x) {
        return read(x) , * this ;
    }
} in ;
struct FILEOUT {
    const static int LIMIT = 0x114514 ;
    char quq[SZ] , ST[0x114] ;
    signed sz , O ;
    ~ FILEOUT () {
        sz = O = 0 ;
    }
    void flush() {
        fwrite(quq , 1 , O , stdout) ;
        fflush(stdout) ;
        O = 0 ;
    }
    FILEOUT & operator << (char c) {
        return quq[O ++] = c , * this ;
    }
    FILEOUT & operator << (string str) {
        if(O > LIMIT) flush() ;
        for(char c : str) quq[O ++] = c ;
        return * this ;
    }
    Tp < class T > void write(T x) {
            if(O > LIMIT) flush() ;
            if(x < 0) {
                quq[O ++] = 0x2d ;
                x = -x ;
            }
            do {
                ST[++ sz] = x % 0xa ^ 0x30 ;
                x /= 0xa ;
            } while(x) ;
            while(sz) quq[O ++] = ST[sz --] ;
            return ;
    }
    FILEOUT & operator << (int x) {
        return write(x) , * this ;
    }
    FILEOUT & operator << (signed x) {
        return write(x) , * this ;
    }
    FILEOUT & operator << (unsigned x) {
        return write(x) , * this ;
    }
} out ;

int n , a , b ;
const int maxn = 52 ;
int f[maxn][maxn][maxn][maxn] ;
int g[maxn][maxn] ;
signed main() {
#ifdef _WIN64
    freopen("testdata.in" , "r" , stdin) ;
#else
    ios_base :: sync_with_stdio(false) ;
    cin.tie(nullptr) , cout.tie(nullptr) ;
#endif
// code begin.
    in >> n >> a >> b ;
    vector < int > v(n) , c(n) ;
    for(int i = 0 ; i < n ; i ++) {
        in >> v[i] ;
        c[i] = v[i] ;
    }
    unique(c) ; int siz = sz(c) ;
    memset(f , 0x3f , sizeof(f)) ;
    memset(g , 0x3f , sizeof(g)) ; 
    for(int i = 0 ; i < n ; i ++) {
        v[i] = lower_bound(all(c) , v[i]) - c.begin() ;
        f[i][i][v[i]][v[i]] = 0 ;
        g[i][i] = a ;
    }
    for(int len = 1 ; len <= n ; len ++) {
        for(int l = 0 ; l + len - 1 < n ; l ++) {
            int r = l + len - 1 ;
            
            for(int mn = 0 ; mn < siz ; mn ++)
                for(int mx = mn ; mx < siz ; mx ++)
                    cmin(f[l][r][min(mn , v[r])][max(mx , v[r])] , f[l][r - 1][mn][mx]) ;
                    
            for(int k = l ; k < r ; k ++)
                for(int mn = 0 ; mn < siz ; mn ++)
                    for(int mx = mn ; mx < siz ; mx ++)
                        cmin(f[l][r][mn][mx] , f[l][k][mn][mx] + g[k + 1][r]) ;
                        
            for(int mn = 0 ; mn < siz ; mn ++)
                for(int mx = mn ; mx < siz ; mx ++)
                    cmin(g[l][r] , f[l][r][mn][mx] + a + b * (c[mx] - c[mn]) * (c[mx] - c[mn])) ;
                    
        }
    }
    out << g[0][n - 1] << '\n' ;
    return out.flush() , 0 ;
// code end.
}
上一篇:Codeforces Global Round 6D(VECTOR >)


下一篇:BZOJ 3691 游行