P10956 金字塔

原题链接

虽然我还是看题解才会做的(菜),但我还要说这题挺简单的(菜),还是菜就多练。

因为是对一个字符串操作求树的可能数,所以考虑区间dp,设状态 \(dp[i][j]\) 为区间 \(i\)\(j\) 树的状态数。

在转移的过程中如果 \(s_i=s_j\) 时代表这可能为同一个根节点组成的树,所以才可以开始枚举中间点,当中间点与根节点的颜色相同时,我们就可以将分为两个子树,然后根据乘法原理,将每个区间状态数相乘就是这么划分的方案数,再将所有的状态数相加就得到了大区间的状态数,转移方程为 \(dp[i][j]=(dp[i][j]+dp[i][k]\times dp[k+1][j-1])\),\(k+1\)\(j-1\) 是为了得到两个不同子树乘积。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9;
const int N=1e5;
char s[N];
int n;
ll dp[1005][1005];
int main(){
ios::sync_with_stdio(false);
cin>>s+1;
n=strlen(s+1);
for(int i=1;i<=n;i++){
dp[i][i]=1;//初始化,只有1种可能
}
for(int len=2;len<=n;len++){//区间长度
for(int i=1;i<=n-len+1;i++){//枚举起点
int j=i+len-1;
if(s[i]==s[j]){//可能合法
for(int k=i;k<=j-1;k++){//枚举中间点
if(s[k]==s[i]){//得到两个子树
dp[i][j]+=(dp[i][k]*dp[k+1][j-1])%mod;
dp[i][j]%=mod;
}
}
}
}
}
cout<<dp[1][n];
return 0;
}
posted @   sad_lin  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示