题目链接: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; }