1. 程式人生 > 實用技巧 >《演算法競賽進階指南》0x53區間DP Acwing284金字塔

《演算法競賽進階指南》0x53區間DP Acwing284金字塔

題目連結:https://www.acwing.com/problem/content/286/

給定一棵樹的DFS序,求這棵樹可能的形狀有多少種?

由於dfs序中,每條邊都訪問兩遍,從根節點進入只有一次,所以在有n個結點的樹的DFS序的長度是2*n-1。根據區間DP,可以先構造這棵樹的最右側的子樹,列舉進入的字串,算出最右側子樹能夠多少種構造方法,與左邊一段的序列構造的樹的數量相乘就得到了一次決策的數量,列舉右子樹的進入點,進行決策的累加就得到了最終區間的決策數量。

注意:子樹的dfs序的長度一定是奇數,所以在列舉左邊序列組成的樹的時候需要其長度是奇數。k=l代表的是左側組成根節點,只有一個點,沒有其餘子樹。

程式碼:

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
const int maxn = 310;
const int mod=1e9;
int f[maxn][maxn];
string s;
int main(){
    cin>>s;
    int n=s.length();
    if(n%2==0)puts("0");
    else{
        for(int len=1;len<=n;len++)
            
for(int l=0;l+len-1<n;l++) { int r=l+len-1; if(len==1)f[l][r]=1; if(s[l]==s[r]){ for(int k=l;k<r;k+=2){//保證子樹的dfs序是奇數 if(s[k]==s[r]){ f[l][r]=(f[l][r]+(long long)f[l][k]*f[k+1
][r-1])%mod; } } } } cout<<f[0][n-1]<<endl; } }