【bzoj4897】[Thu Summer Camp2016成绩单]

【bzoj4897】[Thu Summer Camp2016成绩单]

区间DP神题
Orz GXZ
看了GXZ大神的博客然后懂了.
考虑如何把最大最小值压进状态里.
\(f[l][r]\)表示\(l\)\(j\)删除的最小代价.
\(g[l][r][i][j]\)表示序列\(l\)\(r\)删至最大值为\(i\),最小值为\(j\)的最小代价
然后考虑转移\(g\)
考虑最后一位r.
转移有两种情况:
第一种:它在\([l,r]\)中被整体删除.那么这个时候就要更新最大最小值
\(g[l][r][max(i , w[r]][min(j , w[r])] = g[l][r - 1][i][j]\)
第二种:它在\([k,r]\)中作为子区间删除
\(g[l][r][i][j] = g[l][k][i][j] + f[k + 1][r]\)

考虑f数组的转移
\(f[l][r] = g[l][r][i][j] + a + b * (i - j)^2\)

由于\(w_i\)太大,可以考虑离散化

/*header*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
#define mk make_pair
#define fi first
#define se second
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::lower_bound;
const int maxN = 50 + 7;
 
int f[maxN][maxN];
int g[maxN][maxN][maxN][maxN];
int w[maxN] , s[maxN];
 
inline int gi() {
    int x = 0,f = 1;char c = gc;
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;
}
 
void print(int x) {
    if(x < 0) pc('-') , x = -x;
    if(x >= 10) print(x / 10);
    pc(x % 10 + '0');
}
 
inline int sqr(int x) {
    return x * x;
}

inline void gmin(int &x , int y) {
    x > y ? x = y : 0;
}
 
int main() {
//  freopen("1.in","r",stdin);
    int n =  gi() , a = gi(), b = gi();
    rep(i , 1, n) s[i] = w[i] = gi();
    sort(s + 1,s + n + 1);
    memset(f,0x3f,sizeof(f));memset(g,0x3f,sizeof(g));
    rep(i , 1, n) w[i] = lower_bound(s + 1, s + n + 1, w[i]) - s , f[i][i] = a , g[i][i][w[i]][w[i]] = 0;
    rep(len , 2, n) {
        rep(l , 1, n) {
            int r = l + len - 1;g[l][r][w[r]][w[r]] = f[l][r - 1];
            if(r > n) break;
            rep(i , 1, n) 
                rep(j , 1, i)
                    g[l][r][max(i , w[r])][min(j , w[r])] = min(g[l][r - 1][i][j] , g[l][r][max(i , w[r])][min(j , w[r])]) ;
            rep(k , l, r - 1) 
                rep(i , 1, n)
                    rep(j , i, n)
                        gmin(g[l][r][j][i] , g[l][k][j][i] + f[k + 1][r]);
            rep(i , 1, n) {
                rep(j , i, n) {
                    f[l][r] = min(f[l][r] , g[l][r][j][i] + a + b * sqr(s[j] - s[i])) ;
                }
            }
      }
    }
    print(f[1][n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gzygzy/p/10207196.html