码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-02-25 12:14:44      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:cstring   表示   turn   ++   lap   and   get   方式   status   

合唱队

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

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

Source

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

 

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

标签:cstring   表示   turn   ++   lap   and   get   方式   status   

原文地址:http://www.cnblogs.com/BearChild/p/6441281.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!