《演算法競賽進階指南》0x53區間DP Acwing284金字塔
阿新 • • 發佈:2020-07-30
題目連結: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; } }