金字塔

CH

题意:金字塔由若干房间组成,房间之间连有通道.如果把房间看作节点,通道看作边的话,整个金字塔呈现一个有根树结构,节点的子树之间有序,金字塔有唯一的一个入口通向树根.并且,每个房间的墙壁都涂有若干种颜色的一种.机器人会从入口进入金字塔,之后对金字塔进行深度优先遍历.机器人每进入一个房间(无论是第一次进入还是返回),都会记录这个房间的颜色.最后,机器人会从入口退出金字塔.显然,机器人会访问每个房间至少一次,并且穿越每条通道恰好两次(两个方向各一次),然后,机器人会得到一个颜色序列.但是,颜色序列并不能唯一确定金字塔的结构,请你计算对于一个给定的颜色序列,有多少种可能的结构会得到这个序列,答案对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
",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
",solve(1,s.size()));
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/10939943.html