UVALive - 3516 Exploring Pyramids 【多叉树遍历】

版权声明:本文为博主原创文章,转载请注明出处( • ̀ω•́ )✧ https://blog.csdn.net/wangws_sb/article/details/83959675

题目传送门

题目描述:给出一棵多叉树,每个节点的任意两个子节点都有左右之分。从根节点开始,每次尽量往左走,走不通了就回溯,把遇到的字母顺次记录下来,可以得到一个序列。如下图所示的5个图的序列均为ABABABA

给定一个序列,问有多少棵树与之对应。

输入:输入包含多组数据,每组数据仅一行,即由大写字母组成的访问序列。序列非空且长度不超过300。

输出:对于每组数据,输出满足条件的多叉树的数目除以10^9的余数。

解题思路:设输入序列为s,d[i][j]为子序列s[i],s[i+1],......,s[j]对应的树的个数,则边界条件是d[i][i]=1,且s[i]不等于s[j]时d[i][j]=0(因为起点和终点应是同一点)。在其他情况下,设第一个分支在s[k]时回到树根(必须有s[i]=s[k]),则这个分支对应的序列是s[i+1],......,s[k-1],方案数为d[i+1][k-1];其他分支对应的序列为s[k],.....,s[j],方案数为d[k][j]。由此可得非边界情况时递推关系为:d[i][j]=sum{d[i+1][k-1]*d[k][j] | i+2<=k<=j,s[i]=s[k]=s[j]}。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define inf 0x3f3f3f
typedef long long ll;
const int mod=1000000000;
const int maxn=310;
char s[maxn];
int dp[maxn][maxn];
int DP(int i,int j)
{
    if(i==j)
        return 1;
    if(s[i]!=s[j])
        return 0;
    int& ans=dp[i][j];//&为引用符号,改变ans的同时改变d[i][j]
    if(ans>=0)
        return ans;
    ans=0;
    for(int k=i+2;k<=j;k++)
    {
        if(s[i]==s[k])
            ans=(ans+(ll)DP(i+1,k-1)*(ll)DP(k,j))%mod;
    }
    return ans;
}
int main()
{
    while(scanf("%s",s)==1)
    {
        memset(dp,-1,sizeof(dp));
        printf("%d\n",DP(0,strlen(s)-1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wangws_sb/article/details/83959675