[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; }