bzoj 1996 区间dp
1996: [Hnoi2010]chorus 合唱队
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1727 Solved: 1115
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4
1701 1702 1703 1704
1701 1702 1703 1704
Sample Output
8
HINT
要想知道[l,r]的初始队形的方案数,如果我们知道[l,r-1]和[l+1,r]有几种初始方案的话似乎就可以转移了,但是还是有点问题,我们如何判断不在区间里的那个元素前面的元素的值,根据大或者小往前面或后面插入,如果不知道相对大小似乎不可行,我们可以多开一维记录最后一个元素的位置,只有两种开头或者结尾。
但要注意初始化时对于dp[i][i][0]和dp[i][i][1]只要有一个为零就好了,否则会出现重复的转移,单个元素没什么前后之分。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define mod 19650827 5 int dp[1005][1005][2]; 6 int a[1005]; 7 int f(int l,int r,int x) 8 { 9 if(dp[l][r][x]!=-1) return dp[l][r][x]; 10 if(l==r) return x; 11 int res=0; 12 if(x){ 13 if(a[r]>a[r-1]) res=(res+f(l,r-1,1)); 14 if(a[r]>a[l]) res=(res+f(l,r-1,0)); 15 } 16 else{ 17 if(a[l]<a[r]) res=(res+f(l+1,r,1)); 18 if(a[l]<a[l+1]) res=(res+f(l+1,r,0)); 19 } 20 return dp[l][r][x]=res%mod; 21 } 22 int main() 23 { 24 int N,i,j,k,s; 25 scanf("%d",&N); 26 for(i=1;i<=N;++i) scanf("%d",a+i); 27 memset(dp,-1,sizeof(dp)); 28 printf("%d\n",(f(1,N,1)+f(1,N,0))%mod); 29 return 0; 30 }