zoukankan      html  css  js  c++  java
  • BZOJ4897: [Thu Summer Camp2016]成绩单【DP of DP】

    Description

    期末考试结束了,班主任L老师要将成绩单分发到每位同学手中。L老师共有n份成绩单,按照编号从1到n的顺序叠

    放在桌子上,其中编号为i的成绩单分数为w_i。成绩单是按照批次发放的。发放成绩单时,L老师会从当前的一叠

    成绩单中抽取连续的一段,让这些同学来领取自己的成绩单。当这批同学领取完毕后,L老师再从剩余的成绩单中

    抽取连续的一段,供下一批同学领取。经过若干批次的领取后,成绩单将被全部发放到同学手中。然而,分发成绩

    单是一件令人头痛的事情,一方面要照顾同学们的心理情绪,不能让分数相差太远的同学在同一批领取成绩单;另

    一方面要考虑时间成本,尽量减少领取成绩单的批次数。对于一个分发成绩单的方案,我们定义其代价为:

    img

    其中,k是方案中分发成绩单的批次数,对于第i批分发的成绩单,〖max〗_i是最高分数,〖min〗_i是最低分数。

    a,b是给定的评估参数。现在,请你帮助L老师找到代价最小的分发成绩单的方案,并将这个最小的代价告诉L老师

    。当然,分发成绩单的批次数k是由你决定的。

    Input

    第一行包含一个正整数n,表示成绩单的数量。

    第二行包含两个非负整数a,b,表示给定的评估参数。

    第三行包含n个正整数w_i,表示第i张成绩单上的分数。

    Output

    仅一个正整数,表示最小的代价是多少。

    Sample Input

    10
    3 1
    7 10 9 10 6 7 10 7 1 2

    Sample Output

    15
    【样例数据说明】
    第1批:第2至4份成绩单,落差值为1,剩余成绩单为76710712;
    第2批:第4份成绩单,落差值为0,剩余成绩单为767712;
    第3批:第1至4份成绩单,落差值为1,剩余成绩单为12;
    第4批:剩余的2份成绩单,落差值为1。
    总代价为4×3+(12+02+12+12)×1=15。

    HINT

    n<=50, a<=100, b<=10, w_i<=1000


    思路

    首先考虑dp

    (f_{l,r})表示把区间([l,r])的所有成绩单删除的代价

    然后就不会了,考虑整个区间,要么递归成两个子区间分别处理,或者直接考虑这个区间的最后一次删除

    那么最后一次删除的如果是([p,q])这个区间的数,记录(g_{l,r,p,q})表示区间([l,r])最后只剩下([p,q])的最小代价

    然后f的转移可以枚举(p,q)从g转移也可以划分成两个区间递归成f转移

    g可以划分成两个区间,分别从(g_{l,k,p,q}+g_{k+1,r,p,q},g_{l,k,p,q}+f_{k+1,r},f_{l,k}+g_{k+1,r,p,q})转移


    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 51;
    const int INF_of_int = 1e8;
    
    int f[N][N], g[N][N][N][N];
    int a, b, n, m, w[N], pre[N];
    
    int getg(int l, int r, int down, int up);
    int getf(int l, int r);
    
    int getg(int l, int r, int down, int up) {
      if (~g[l][r][down][up]) return g[l][r][down][up];
      if (l == r) return g[l][r][down][up] = (down <= w[l] && w[l] <= up) ? 0 : INF_of_int;
      int &cur = g[l][r][down][up];
      cur = INF_of_int;
      for (int k = l; k < r; k++) {
        cur = min(cur, getg(l, k, down, up) + getg(k + 1, r, down, up));
        cur = min(cur, getg(l, k, down, up) + getf(k + 1, r));
        cur = min(cur, getf(l, k) + getg(k + 1, r, down, up));
      }
      return cur;
    }
    
    int getf(int l, int r) {
      if (~f[l][r]) return f[l][r];
      if (l == r) return f[l][r] = a;
      int &cur = f[l][r];
      cur = INF_of_int;
      for (int i = 1; i <= m; i++)
        for (int j = i; j <= m; j++)
          cur = min(cur, getg(l, r, i, j) + a + b * (pre[j] - pre[i]) * (pre[j] - pre[i]));
      for (int k = l; k < r; k++)
        cur = min(cur, getf(l, k) + getf(k + 1, r));
      return cur;
    }
    
    int main() {
    #ifdef dream_maker
      freopen("input.txt", "r", stdin);
    #endif
      memset(f, -1, sizeof(f));
      memset(g, -1, sizeof(g));
      scanf("%d %d %d", &n, &a, &b);
      for (int i = 1; i <= n; i++) {
        scanf("%d", &w[i]);
        pre[i] = w[i];
      }
      sort(pre + 1, pre + n + 1);
      m = unique(pre + 1, pre + n + 1) - pre - 1;
      for (int i = 1; i <= n; i++)
        w[i] = lower_bound(pre + 1, pre + m + 1, w[i]) - pre;
      printf("%d", getf(1, n));
      return 0;
    }
    
  • 相关阅读:
    tfidf 问题
    Win32汇编窗口程序设计[03]第一个窗口程序
    Win32汇编窗口程序设计[01]开发环境的搭建
    Win32汇编窗口程序设计[02]RadASM简介
    寄存器引用结构体变量
    始终居中的弹出层
    JSonJavaScript
    json
    <收录>jqueryuidatapicker生成的页面html
    网站数据抓取
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/10196404.html
Copyright © 2011-2022 走看看