牛客 金字塔

https://ac.nowcoder.com/acm/contest/1043/C

题面

给定一个树的遍历序列,其中不同的点可能有相同的标记,求可能的树的数量
\(n\leq 300\)

分析

显然区间DP,\(f[i][j]\)表示这区间的可能树的数量
然后枚举第一棵子树,防止重复统计
\(f[i][j]=\begin{cases} 0,a_i\neq a_j\\ 1,i\neq j\\ f[i+1][j-1]+\sum_{k=i+1,a[k]==a[i]}^{k=j-1}f[i+1][k-1]\times f[k][j],else \end{cases}\tag{1}\)

#include<bits/stdc++.h>
#define ll long long
const int p=1e9;
using namespace std;

const int N=305;
int n,f[N][N];
char a[N];
int main() {
	scanf("%s",a+1); n=strlen(a+1);
	for(int i=1;i<=n;i++) f[i][i]=1;
	for(int l=2;l<=n;l++) {
		for(int i=1,j=i+l-1;j<=n;i++,j++) {
			if(a[i]==a[j]) {
				f[i][j]=f[i+1][j-1];
				for(int k=i+1;k<=j-1;k++) {
					if(a[k]==a[i]) {
						f[i][j]=((ll)f[i][j]+(ll)f[i+1][k-1]*f[k][j])%p;
					}
				}
			}
		}
	}
	printf("%d\n",f[1][n]);
	return 0;
}
posted @ 2020-11-30 19:42  wwwsfff  阅读(119)  评论(0)    收藏  举报