• 【BZOJ1996】【HNOI2010】合唱队 [区间DP]


    合唱队

    Time Limit: 4 Sec  Memory Limit: 64 MB
    [Submit][Status][Discuss]

    Description

      

    Input

      

    Output

      

    Sample Input

      4
      1701 1702 1703 1704

    Sample Output

      8

    HINT

      

    Main idea

      给定一个元素两两不相等的目标序列,每次按照给定方式将一个元素加入到序列当中,问得到目标序列的方案有几种。(加元素的方式:如果加的这个元素比上一个加入的元素小的话则放在队头,否则放在队尾)。

    Solution

      发现题目要求的是方案数,并且没有什么一眼看过去的规律,不可能是找规律了,那么我们想到了区间DP
      由于题目给定的加入元素的方式,我们可以清楚的知道新元素要么加在队头要么加在队尾,所以说在某种程度上这个序列是连续的(或者说有特殊的性质),并且对于新加入的元素的位置的影响只跟上一次的加入元素有关。
      根据这个特殊性质我们想到了区间DP,令f[l][r][01]表示区间l~r中现在加入的元素放在队头队尾
      那么显然,初值即为f[i][i][0]=1或f[i][i][1]=1,并且如果放在队头的话f[l][r][0]应该从f[l+1][r][01]推导过来,继续思考发现从f[l+1][r][0]推导过来的条件是a[l]<a[l+1],从f[l][r][1]推导过来的条件则应该是a[l]<a[r],f[l][r][1]情况类似。
      这样跑一遍区间DP最后答案显然就是f[1][n][0]+f[1][n][1]了。

    Code

     1 #include<iostream>  
     2 #include<algorithm>  
     3 #include<cstdio>  
     4 #include<cstring>  
     5 #include<cstdlib>  
     6 #include<cmath>
     7 #include<queue>
     8 using namespace std;  
     9        
    10 const int ONE=1005;
    11 const int MOD=19650827;
    12  
    13 int n;
    14 int a[ONE];
    15 int f[ONE][ONE][2];
    16  
    17 int get()
    18 {
    19         int res,Q=1;    char c;
    20         while( (c=getchar())<48 || c>57)
    21         if(c=='-')Q=-1;
    22         if(Q) res=c-48; 
    23         while((c=getchar())>=48 && c<=57) 
    24         res=res*10+c-48; 
    25         return res*Q; 
    26 }
    27  
    28 int main()
    29 {
    30         n=get();
    31         for(int i=1;i<=n;i++)
    32         {
    33             a[i]=get();
    34         }
    35          
    36         for(int i=1;i<=n;i++) f[i][i][1]=1;
    37          
    38         for(int l=n;l>=1;l--)
    39         for(int r=l+1;r<=n;r++)
    40         {
    41             f[l][r][0]=( f[l][r][0] + f[l+1][r][0] * (a[l]<a[l+1]) ) % MOD;
    42             f[l][r][0]=( f[l][r][0] + f[l+1][r][1] * (a[l]<a[r]) ) % MOD; 
    43             f[l][r][1]=( f[l][r][1] + f[l][r-1][0] * (a[r]>a[l]) ) % MOD;
    44             f[l][r][1]=( f[l][r][1] + f[l][r-1][1] * (a[r]>a[r-1]) ) % MOD;
    45         }
    46          
    47         printf("%d",(f[1][n][0]+f[1][n][1]) % MOD);
    48 }
    View Code

     

  • 相关阅读:
    CODING DevOps 高级架构师王炜入选木兰开源社区首批导师
    夯实基础,踏步云升 | 云原生 DevOps 入门必读
    Cloud Studio 2.0:云的开端
    持续演进的云原生应用交付
    CODING 携手 CoDesign:让设计与开发更简单
    代码扫描 | 把控代码质量的利器
    CODING 持续集成 | 自定义插件,满足你多样化的构建需求
    随便侃侃博客挖坑的事
    如何解决快应用页面滑动卡顿问题
    【HMS Core 6.0全球上线】华为3D建模服务(3D Modeling Kit),轻松构建高质量3D模型
  • 原文地址:https://www.cnblogs.com/BearChild/p/6441281.html
Copyright © 2020-2023  润新知