題目大意:
定義乙個串:只含有 '( )','[ ]','',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,...