洛谷 P3205 [HNOI2010]合唱队(区间dp)

传送门


解题思路

观察队形的组成方式可以得出,最后一名加入区间i...j的人要么是在i位置上,要么是在j位置上,所以我们可以用dp[i][j][0]表示区间i...j最后一个加入的人站在i位置上的方案总数,同理,用dp[i][j][1]表示区间i...j最后一个加入的人站在j位置上的方案总数。

然后分情况讨论即可。

最后答案等于dp[1][n][0]+dp[1][n][1]。

别忘了对所有的操作进行取余。

AC代码

 1 #include<iostream>
 2 using namespace std;
 3 int n,dp[1005][1005][2],a[1005];
 4 const int mod=19650827;
 5 int main()
 6 {
 7     cin>>n;
 8     for(int i=1;i<=n;i++){
 9         cin>>a[i];
10         dp[i][i][0]=dp[i][i][1]=1;
11     }
12     for(int i=1;i<=n;i++){
13         int j=i+1;
14         if(j>n) break;
15         if(a[i]<a[j]) dp[i][j][0]=dp[i][j][1]=1;
16     }
17     for(int len=3;len<=n;len++){
18         for(int i=1;i<=n;i++){
19             int j=i+len-1;
20             if(j>n) break;
21             if(a[i]<a[i+1]){
22                 dp[i][j][0]+=dp[i+1][j][0];
23             }
24             if(a[i]<a[j]){
25                 dp[i][j][0]+=dp[i+1][j][1];
26             }
27             if(a[j]>a[i]){
28                 dp[i][j][1]+=dp[i][j-1][0];
29             }
30             if(a[j]>a[j-1]){
31                 dp[i][j][1]+=dp[i][j-1][1];
32             }
33             dp[i][j][0]%=mod;
34             dp[i][j][1]%=mod;
35         }
36     }
37     cout<<(dp[1][n][0]+dp[1][n][1])%mod;
38     return 0;
39 }
原文地址:https://www.cnblogs.com/yinyuqin/p/12375158.html