牛客NC21303删括号(判定性DP)

僤鯓⒐⒋嵵緔 提交于 2020-02-11 16:56:55

NC21303 删括号

题目链接:https://ac.nowcoder.com/acm/problem/21303

题目描述
给你一个合法的括号序列s1,每次你可以删除一个"()"
你可以删除0个或者多个"()"
求能否删成另一个括号序列s2
输入描述:
第一行输入一个字符串s (2 ≤ |s| ≤ 100)
第二行输入一个字符串t (2 ≤ |t| ≤ 100 )
输出描述:
如果可以输出"Possible"
否则输出"Impossible"
示例1
输入
(())
()
输出
Possible
示例2
输入
()
()
输出
Possible
示例3
输入
(()()())
((()))
输出
Impossible
示例4
输入
((())((())())())
(()(())())
输出
Possible
示例5
输入
((())((())())())
((()()()()()))
输出
Impossible


判定性DP😲???没见过这种DP,所以也是现学的,看的题解才明白。

题目中的条件合法的括号序列很重要
定义 dp[i][j][k]dp[i][j][k] 为A前ii个与B前jj个被删去 k=删去左括号数-删去右括号数 的情况下是否可行。当k==0时删去的括号是成对的。分类讨论转移,最后答案就是 dp[a.length][b.length][0]dp[a.length][b.length][0]
这里不是很明白怎么转移的。等以后再填坑

Code:

#include <bits/stdc++.h>
#define IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;
string a, b;
bool dp[110][110][55]; // dp[i][j][k],a的前i个,b的前j个,k表示在a的前i个中删去'('的数量减删去')'的数量,也就是说k表示多删掉的左括号的数量。因为是合法的括号序列,所以k一定是大于等于0的,当k==0时,就是删去了成对的括号。
int main()
{
    IO;
    cin >> a >> b;
    int la = a.length();
    int lb = b.length();
    memset(dp, false, sizeof(dp));
    dp[0][0][0] = true; // 初始值很重要
    for (int i = 0; i < la; i++)
    {
        for (int j = 0; j < lb; j++)
        {
            for (int k = 0; k <= la / 2; k++)
            {
                if (dp[i][j][k])
                {
                    if (k == 0 && a[i + 1] == b[j + 1])
                    {
                        dp[i + 1][j + 1][k] = true;
                    }
                    if (a[i + 1] == '(')
                    {
                        dp[i + 1][j][k + 1] = true;
                    }
                    else if (k)
                    {
                        dp[i + 1][j][k - 1] = true;
                    }
                }
            }
        }
    }
    if (dp[la][lb][0])
        cout << "Possible" << endl;
    else
        cout << "Impossible" << endl;
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!