UVA1362 Exploring Pyramids
题意
给定一棵树的 序 ,求这棵树的形态数量,答案对 取模。
有多组数据。
分析
我们知道,一棵树的 序长这样:
根|子树 1|根|子树 2|根|子树 3|根|……|根|子树 n|根
因为可能会有相同的颜色,所以与根颜色相同的节点也可能为子树。
一棵树的形态个数显然由它子树的形态个数得到,于是我们设 为以区间 为树的形态的个数。
显然,若 ,;若 ,。
接下来考虑 的情况:
- 只有一颗子树。
此时树的形态为 根|子树 1|根
,这时树的形态数量就是子树 的形态数量个数,即 。
- 有多棵子树。
此时树的形态为 根|子树 1|根|其他子树|根
,我们发现其中 子树 1
和 根|其他子树|根
是两个子问题,于是我们枚举子树 的根端点 ,满足 ,根据乘法原理及加法原理,。
答案为 。
像这样,一个大区间的答案从小区间得到,我们就想到了区间 dp。
然后就是板子了。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
long long x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void write(long long x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=310;
const ll mod=1e9;
string s;
int n;
ll dp[N][N];
int main(){
while(cin>>s){
n=s.size();
s=" "+s;//字符串下标从0开始,前面加一个空格使下标从1开始
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
dp[i][i]=1;
for(int l=2;l<=n;l++){
for(int i=1,j;i+l-1<=n;i++){
j=i+l-1;
if(s[i]!=s[j])
continue;
dp[i][j]=dp[i+1][j-1];
for(int k=i+2;k<=j-2;k++)
if(s[i]==s[k])
dp[i][j]=(dp[i][j]+dp[i+1][k-1]*dp[k][j]%mod)%mod;
}
}
write(dp[1][n]);
putchar('\n');
}
return 0;
}
本文作者:luckydrawbox
本文链接:https://www.cnblogs.com/luckydrawbox/p/18526592
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步