删括号

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

  

posted @ 2021-02-07 15:35  ACM-Epoch  阅读(88)  评论(0编辑  收藏  举报