NC21303 删括号
题目描述
给你一个合法的括号序列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,所以也是现学的,看的题解才明白。
题目中的条件合法的括号序列很重要。
定义 为A前个与B前个被删去 k=删去左括号数-删去右括号数 的情况下是否可行。当k==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;
}
来源:CSDN
作者:海星**
链接:https://blog.csdn.net/weixin_44169557/article/details/104261365