[luoguP3205] [HNOI2010]CHORUS 合唱队(区间DP)

传送门

 

注意到只能在两边加人,有一种区间dp的感觉。

f[i][j][0/1]表示已经搞完区间[i,j]且上次搞的是左/右的方案数

那么他只能从f[i+1][j]或f[i][j-1]的某种状态得到,随便yy以下就知道状态转移方程了

 

#include <cstdio>
#include <cstring>
#include <iostream>
#define N 2010
#define p 19650827

using namespace std;

int n;
int a[N], f[N][N][2];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline int dfs(int l, int r, int x)
{
	if(f[l][r][x] != -1) return f[l][r][x];
	int tmp = 0;
	if(!x)
	{
		if(a[l] < a[l + 1]) tmp += dfs(l + 1, r, 0);
		if(a[l] < a[r]) tmp += dfs(l + 1, r, 1);
	}
	else
	{
		if(a[r] > a[l]) tmp += dfs(l, r - 1, 0);
		if(a[r] > a[r - 1]) tmp += dfs(l, r - 1, 1);
	}
	return f[l][r][x] = tmp % p;
}

int main()
{
	int i;
	n = read();
	memset(f, -1, sizeof(f));
	for(i = 1; i <= n; i++)
	{
		a[i] = read();
		f[i][i][0] = 1;
		f[i][i][1] = 0;
	}
	printf("%d\n", (dfs(1, n, 0) + dfs(1, n, 1)) % p);
	return 0;
}

  

posted @ 2018-01-19 10:15  zht467  阅读(130)  评论(0编辑  收藏