Codeforces Round #554 (Div. 2) D 貪心 + 記憶化搜索
阿新 • • 發佈:2019-05-05
com problem ble 搜索 括號序列 long 記憶化 i++ 貪心
https://codeforces.com/contest/1152/problem/D
題意
給你一個n代表合法括號序列的長度一半,一顆有所有合法括號序列構成的字典樹上,選擇最大的邊集,邊集的邊沒有公共點,問邊集大小
題解
- 對於一顆字典樹,從低向上貪心,最底層的邊全拿,定義好狀態,記憶化搜索計數
- 定義dp[i][j]為左括號數量為i,右括號數量為j的最大邊集
- \(i<n\),\(dp[i][j]->dfs(i+1,j)\)
- \(j<i\),\(dp[i][j]->dfs(i,j+1)\)
- 註意一下,相鄰兩層不能連續選邊
代碼
#include<bits/stdc++.h> #define ll long long #define P 1000000007 #define pii pair<ll,int> #define mk make_pair #define ft first #define se second using namespace std; pii dp[1005][1005]; int n; pii dfs(int i,int j){ if(i==n&&j==n)return mk(0,0); pii &ans=dp[i][j]; if(ans.ft>=0)return ans; ans=mk(0,1); if(i<n){ pii tp=dfs(i+1,j); ans.ft+=tp.ft;ans.ft%=P; ans.se&=tp.se; } if(j<i){ pii tp=dfs(i,j+1); ans.ft+=tp.ft;ans.ft%=P; ans.se&=tp.se; } if(ans.se==0){ans.ft++;ans.ft%=P;} ans.se^=1; return ans; } int main(){ cin>>n; for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)dp[i][j]=mk(-1,-1); cout<<dfs(1,0).ft; }
Codeforces Round #554 (Div. 2) D 貪心 + 記憶化搜索