题意:金字塔由若干房间组成,房间之间连有通道.如果把房间看作节点,通道看作边的话,整个金字塔呈现一个有根树结构,节点的子树之间有序,金字塔有唯一的一个入口通向树根.并且,每个房间的墙壁都涂有若干种颜色的一种.机器人会从入口进入金字塔,之后对金字塔进行深度优先遍历.机器人每进入一个房间(无论是第一次进入还是返回),都会记录这个房间的颜色.最后,机器人会从入口退出金字塔.显然,机器人会访问每个房间至少一次,并且穿越每条通道恰好两次(两个方向各一次),然后,机器人会得到一个颜色序列.但是,颜色序列并不能唯一确定金字塔的结构,请你计算对于一个给定的颜色序列,有多少种可能的结构会得到这个序列,答案对1e9取模.
DP实现:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int mod=1e9;
LL f[305][305];
int main(){
string s;cin>>s;
for(int i=1;i<=s.size();++i)f[i][i]=1;
for(int j=1;j<=s.size();++j)
for(int i=j-1;i;--i){
if(s[i-1]!=s[j-1])continue;
for(int k=i;k<=j;++k){
if(s[i-1]!=s[k-1])continue;
f[i][j]+=f[i+1][k-1]*f[k][j]%mod;
}
f[i][j]%=mod;
}
printf("%lld\n",f[1][s.size()]);
return 0;
}
记忆化搜索实现:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
const int mod=1e9;
string s;int f[305][305];
inline int solve(int l,int r){
if(l==r)return 1;
if(f[l][r]!=-1)return f[l][r];
if(s[l-1]!=s[r-1])return 0;
f[l][r]=0;
for(int k=l+2;k<=r;k++)
if(s[k-1]==s[l-1])f[l][r]=(f[l][r]+(1ll*solve(l+1,k-1)*solve(k,r))%mod)%mod;
return f[l][r];
}
int main(){
memset(f,-1,sizeof(f));
cin>>s;printf("%d\n",solve(1,s.size()));
return 0;
}