zoukankan      html  css  js  c++  java
  • LOJ 2292 「THUSC 2016」成绩单——区间DP

    题目:https://loj.ac/problem/2292

    直接 DP 很难做,主要是有那种 “一个区间内部有很多个别的区间” 的情况。

    自己想了一番枚举 max-min 的最大限制,然后在该基础上最小化区间个数之类的。还是不会。

    看了题解才会。

    考虑再设一个 dp 数组来辅助表示那种麻烦的情况。

    值可以离散化!又因为代价与值有关,可以考虑把值放进角标里。

    令 f[ i ][ j ] 表示把 [ i , j ] 全取完的最小代价,g[ i ][ j ][ l ][ r ] 表示把 [ i , j ] 取得只剩下值在 [ l , r ] 之间的最小代价。

    g[ i ][ j ][ l ][ r ] 转移时讨论一下 j 是否留下。若留下,则从 g[ i ][ j-1 ][ l ][ r ] 转移,否则枚举和 j 一起删掉的区间,从 g[ i ][ k-1 ][ l ][ r ] + f[ k ][ j ] 转移。

    然后 f[ i ][ j ] 就是各种 g[ i ][ j ][ l ][ r ] 再加上把值在 [ l , r ] 的数一次取完的代价。

    这种设状态为 “做到剩下特定元素” 的思想很好。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int Mx(int a,int b){return a>b?a:b;}
    int Mn(int a,int b){return a<b?a:b;}
    const int N=55,INF=1005;
    int n,m,A,B,a[N],tp[N],f[N][N],g[N][N][N][N];
    int Sqr(int x){return x*x;}
    void cz(int &u,int v){if(v<u)u=v;}
    int main()
    {
      scanf("%d%d%d",&n,&A,&B);
      for(int i=1;i<=n;i++)scanf("%d",&a[i]),tp[i]=a[i];
      sort(tp+1,tp+n+1); m=unique(tp+1,tp+n+1)-tp-1;
      for(int i=1;i<=n;i++)a[i]=lower_bound(tp+1,tp+m+1,a[i])-tp;
      memset(g,0x3f,sizeof g);
      for(int i=1;i<=n;i++)
        {
          f[i][i]=A;
          for(int l=1;l<=m;l++)
        for(int r=l;r<=m;r++)
          {
            if(a[i]>=l&&a[i]<=r)g[i][i][l][r]=0;
            else g[i][i][l][r]=A;
          }
        }
      for(int d=1;d<n;d++)
        for(int i=1;i+d<=n;i++)
          {
        int j=i+d; int mx=0,mn=INF;
        for(int k=i;k<=j;k++)
          mx=Mx(mx,a[k]),mn=Mn(mn,a[k]);
        f[i][j]=A+B*Sqr(tp[mx]-tp[mn]);
        for(int l=1;l<=m;l++)
          for(int r=l;r<=m;r++)
            {
              if(a[j]>=l&&a[j]<=r)
            cz(g[i][j][l][r],g[i][j-1][l][r]);
              for(int k=i+1;k<=j;k++)
            cz(g[i][j][l][r],g[i][k-1][l][r]+f[k][j]);
              cz(f[i][j],g[i][j][l][r]+A+B*Sqr(tp[r]-tp[l]));
            }
          }
      printf("%d
    ",f[1][n]);
      return 0;
    }
  • 相关阅读:
    [RxSwift]3.3、数据绑定(订阅)
    [RxSwift]3.2、函数式编程 -> 函数响应式编程
    [RxSwift]2、Hello RxSwift!:我的第一个 RxSwift 应用程序
    [RxSwift]1、为什么要使用 RxSwift ?
    [RxSwift]RxSwift: ReactiveX for Swift
    [Swift]UIViewController
    104. 二叉树的最大深度
    103. 二叉树的锯齿形层次遍历
    102. 二叉树的层序遍历
    98. 验证二叉搜索树
  • 原文地址:https://www.cnblogs.com/Narh/p/10735852.html
Copyright © 2011-2022 走看看