POJ1187 隕石的秘密

2022-05-20 14:15:29 字數 1327 閱讀 6431

題目大意:

定義乙個串:只含有 '( )','[ ]','',3種(6個)字元。

定義 ss 串:

空串是ss表示式。

若a是ss表示式,且a串中不含有中括號和大括號,則(a)是ss表示式。

若a是ss表示式,且a串中不含有大括號,則[a]是ss表示式。

若a是ss表示式,則是ss表示式。

定義ss串深度:

空串深度為0.

若a可以寫成*a'*,其中a『為ss串,*為任意括號,則\(d(a)=d(a』)+1\)。

若a可以寫成bc的形式,其中b、c均是ss串,則\(d(a)=max\\)。

求由l1個對括號,l2對中括號,l3對大括號,深度為d 構成的ss串的個數。

題解:這是一道字串上的計數類 dp 問題,一般對於字串計數類問題都先把字串劃分成若干個獨立的部分,即:劃分子問題,再進行求解。首先是狀態的選擇,\(dp[d][i][j][k]\) 表示深度不超過 d,且由 i,j,k 個對應括號構成的ss串的個數,之所以選擇深度不超過 d,是因為若選擇深度恰好為 d,將很難從子狀態轉移到當前狀態,或者說,要考慮的情況也比較多。轉移到狀態轉移如下:

在看題解時,看到了另一種比較優秀的解釋:對於每乙個括號序列可以看成是一棵樹的 dfs 序列(類似 dfs 序),樹的最大深度是 d,求計數。

記憶化搜搜版**如下

#include #include #include #include using namespace std;

const int mod=11380;

int dp[31][11][11][11],l1,l2,l3,d;

int dfs(int dep,int x,int y,int z)

if(x+y+z==0)return 1;

if(ans>=0)return ans;

int cnt=0;

for(int i=0;i迭代版**如下

#include #include #include #include #include using namespace std;

const int p = 11380;

const int m = 35;

const int n = 15;

int f[n][n][n][m];

int fun(int a, int b, int c, int d)

int main()

poj 1187 隕石的秘密

題目大意 求出指定要求的字串的種數,用dp a b c d 記錄有a個 b個,c個 深度為d的字串的個數,然後列舉左邊一段外層加括號的狀態,與右邊對應狀態相乘即可。include include include include include include include include incl...

題解 POJ1187 隕石的秘密

一開始很愉快地想到了乙個dp,然後發現ab c和a bc這兩種情況會重複計數。但其實在列舉a b型時,可以強制令a一定形如 c 這樣就可以避免重複計數了。include include includeusing namespace std const int mod 11380 int l1,l2,...

題解 POJ1187 隕石的秘密

一開始很愉快地想到了乙個dp,然後發現ab c和a bc這兩種情況會重複計數。但其實在列舉a b型時,可以強制令a一定形如 c 這樣就可以避免重複計數了。include include includeusing namespace std const int mod 11380 int l1,l2,...