[HNOI2010] 合唱队 chorus

标签:区间DP。
题解:

  首先分析题目,根据题目中的列队方式以及数据范围,我们容易想到O(n2)的算法,也就是区间DP。发现直接dp[L][R],不能转移,于是添加一个dp[L][R][0/1],0表示这个区间最后从左边插入,1则表示右边。
  然后分析从左边插入,上一个数要么是从左的要么是从右的,因为这个数在左,所以都要比他们大才符合条件。故(H[L]<H[L+1]||H[L]<H[R]),符合条件才能转移:dp[L][R][0]=dp[L+1][R][0]*(H[L]<H[L+1])+dp[L+1][R][1]*(H[L]<H[R]);
  从右边插入类似:(H[R]>H[L]||H[R]>H[R-1]),dp[L][R][1]=dp[L][R-1][0]*(H[R]>H[L])+dp[L][R-1][1]*(H[R]>H[R-1]);
  然后答案自然就是dp[1][n][0]+dp[1][n][1]了。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #define LL long long
 5 using namespace std;
 6 const int MAXN=1100,mod=19650827,INF=0x3f3f3f3f;
 7 int n;
 8 int H[MAXN],dp[MAXN][MAXN][2];
 9 int gi(){ int res; scanf("%d",&res); return res;}
10 int main()
11 {
12   freopen("chorus.in","r",stdin);
13   freopen("chorus.out","w",stdout);
14   n=gi();
15   for(int i=1;i<=n;i++) H[i]=gi();
16   for(int i=1;i<n;i++)
17     {
18       if(H[i]<H[i+1])
19         {        
20           dp[i][i+1][0]=1;
21           dp[i][i+1][1]=1;
22         }
23     }
24   for(int i=2;i<n;i++)
25     {
26       for(int j=1;j+i<=n;j++)
27         {
28           int L=j,R=j+i;
29           dp[L][R][0]=(dp[L+1][R][0]*(H[L]<H[L+1])+dp[L+1][R][1]*(H[L]<H[R]))%mod;
30           dp[L][R][1]=(dp[L][R-1][0]*(H[R]>H[L])+dp[L][R-1][1]*(H[R]>H[R-1]))%mod;
31         }
32     }
33   printf("%d\n",(dp[1][n][0]+dp[1][n][1])%mod);
34   return 0;
35 }

转载于:https://www.cnblogs.com/D-O-Time/p/7986391.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值