[HNOI2010] 合唱队

题目链接:https://www.luogu.org/problemnew/show/P3205
一个区间DP的题目。

设计状态为:\(dp1[i][j]\)表示当前区间为\([i,j]\),而且最后一个放入的在\(i\)位置,\(dp2[i][j]\)表示当前区间为\([i,j]\),而且最后一个放入的在\(j\)位置。

那么状态转移就是:

if(a[i]<a[i+1]) 
	dp1[i][j]+=dp1[i+1][j];
if(a[i]<a[j])   
	dp1[i][j]+=dp2[i+1][j];
if(a[j]>a[i])   
	dp2[i][j]+=dp1[i][j-1];
if(a[j]>a[j-1]) 
	dp2[i][j]+=dp2[i][j-1];

注意初始化有两种qwq:\(dp1[i][i]=1\)\(dp2[i][i]=1\),因为是加法原理累加,所以写一个就可以了。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 1010
#define mod 19650827
using namespace std;
int n;
int a[MAXN],dp1[MAXN][MAXN],dp2[MAXN][MAXN];
int main()
{

    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) dp1[i][i]=1;
    for(int i=n-1;i>=1;i--)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(a[i]<a[i+1]) dp1[i][j]+=dp1[i+1][j],dp1[i][j]%=mod;
            if(a[i]<a[j]) dp1[i][j]+=dp2[i+1][j],dp1[i][j]%=mod;
            if(a[j]>a[i]) dp2[i][j]+=dp1[i][j-1],dp2[i][j]%=mod;
            if(a[j]>a[j-1]) dp2[i][j]+=dp2[i][j-1],dp2[i][j]%=mod;
        }
    }
    printf("%d\n",(dp1[1][n]+dp2[1][n])%mod);
    return 0;
}
posted @ 2018-11-07 11:14  风浔凌  阅读(290)  评论(0编辑  收藏  举报