1 条题解
-
0
一道结合背包的思想(dp)、dp通过两维的和为来定值来将降到的优化、括号匹配的思想(栈)、前缀和的思想(转化成-1和+1)的好题。
首先根据题目给出的定义,我们可以考虑进行一个转化,把左括号看成 ,右括号看成 ,这样合法括号序列可以看成任意前缀和非负、区间和为 的序列。
我们由此可以列出一个 的动态规划方案:表示染色到第 项,标记G的前缀和为 ,标记H的前缀和为 的方案。
转移如下:$dp_{i,j,k} = dp_{i-1,j - A_i,k} + dp_{i-1,j,k - A_i}$,初始化,其中 表示经过转换之后我们的数组的第 项。
但是这个方法时间复杂度很高,我们考虑进一步优化。
我们发现对于一个 而言,有用的 是不变的,即数组 的前 项的前缀和,这点观察式子也可以发现。
所以我们只维护 一维,保证 不为负数即可。
非负如何保证?我们发现,其中 是当前前项的前缀和,我们只要保证即可。
时间复杂度:
#include <iostream> #include <vector> #define endl '\n' using namespace std; using LL = long long; const int mod = 998244353; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s; cin >> s; int n = s.size(); s = " " + s; vector<int> a(n + 1); vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0)); for(int i = 1; i <= n; i++){ if(s[i] == '(') a[i] = 1; else a[i] = -1; } dp[0][0] = 1; LL sum = 0; for(int i = 1; i <= n; i++){ sum += a[i]; for(int j = 0; j <= sum; j++){ dp[i][j] = dp[i - 1][j]; if(j - a[i] >= 0) dp[i][j] = (dp[i][j] + dp[i - 1][j - a[i]]) % mod; } } cout << dp[n][0] << endl; return 0; }
- 1
信息
- ID
- 2281
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 7
- 已通过
- 1
- 上传者