删括号
题目链接:https://ac.nowcoder.com/acm/problem/21303
思路:
- 状态表示
- dp[i][j][k]:s1的前i个字符通过删除掉k(删除的左括号数 - 删除的右括号数)后,能与s2的前j个字符匹配
- 状态属性
- 为bool类型,最终答案是dp[len1][len2][0]的真值,代表s1可以通过删除一些括号对后,能与s2匹配
- 状态计算
-
所以说在状态dp[i][j][k]=true的情况下,对于两个串的下一个字符,只有以下四种情况

-
对于第一种情况,可以推出dp[i+1][j+1][k]=true或dp[i+1][j][k+1]=true;
-
对于第二种情况可以推出dp[i+1][j][k+1]=true;
-
对于第三种情况可以推出dp[i+1][j+1][k]=true或dp[i+1][j][k-1]=true;
-
对于第四种情况可以推出dp[i+1][j][k-1]=true;
-
综合一下就是如果后一个字符相等且k=0,那么dp[i+1][j+1][0]=true,然后如果s的后一个字符是左括号,那么dp[i+1][j][k+1]=true,如果都不满足,并且k!=0,那么dp[i+1][j][k-1]=true.
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 110;
int main() {
string s1, s2; cin >> s1 >> s2;
s1 = ' ' + s1; s2 = ' ' + s2;
ll len1 = s1.size(), len2 = s2.size();
bool dp[N][N][N];
memset(dp, false, sizeof(dp));
dp[0][0][0] = true;
for(int i = 0; i < len1; i++)
for(int j = 0; j < len2; j++)
for(int k = 0; k < len1 / 2; k++)
if(dp[i][j][k]) {
if(!k && s1[i + 1] == s2[j + 1]) dp[i + 1][j + 1][k] = 1;
if(s1[i + 1] == '(') dp[i + 1][j][k + 1] = 1;
else if(k) dp[i + 1][j ][k - 1] = 1;
}
if(dp[len1][len2][0]) cout << "Possible";
else cout << "Impossible";
return 0;
}

浙公网安备 33010602011771号