牛客_21303删括号_动态规划

21303删括号

对我来说这题是真的难以理解,下面展示了完整的思考过程,虽然最后依然有点儿晕。。

题目描述

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

示例1
输入
(())
()
输出
Possible

示例2
输入
()
()
输出
Possible

示例3
输入
(()()())
((()))
输出
Impossible

示例4
输入
((())((())())())
(()(())())
输出
Possible

示例5
输入
((())((())())())
((()()()()()))
输出
Impossible

备注:
子任务1: |s| <= 10
子任务2: |s| <= 20
子任务3: 无限制

题意简析

首先是题意理解:
题目所说的可删的括号必须相邻且"可动态",即((()()))在删()()后,可继续删(),再删().
题目说序列s1合法,即"(“与”)"数目一定相同,且可配对

读题完毕,然后发现不会做,看了诸多题解,来,先贴上一篇整合代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
    string s,t;
    cin>>s>>t;
    int len1=s.length();
    int len2=t.length();
    bool dp[150][10][55];
    memset(dp,0,sizeof(dp));
    dp[0][0][0]=true; 
	//dp[i][j][k]表示考虑s前i个匹配了t前j个,s被删除部分左括号数-右括号数=k是否可行(bool类型)
    for(int q=0;q<len1;q++)
	{
        for(int w=0;w<len2;w++)
		{
            for(int e=0;e<len1/2;e++)
			{
                if(dp[q][w][e])
				{
                    if(e==0&&s[q+1]==t[w+1]) 
						dp[q+1][w+1][0]=true;
                    if(s[q+1]=='(') 
						dp[q+1][w][e+1]=true;
                    else if(e) 
						dp[q+1][w][e-1]=true;
                }
            }
        }
    }
    if(dp[len1][len2][0]) 
		cout<<"Possible"<<endl;
    else    
		cout<<"Impossible"<<endl;
    return 0;
}

代码原理

下面是我强行依据代码胡思乱想5个小时的成果。。。

设两序列为s,t,长度分别为len1,len2,用dp[q][w][e]表示考虑s前q个匹配了t前w个,s被删除部分左括号数-右括号数=e是否可行(bool类型),从前向后遍历,因为必然是删除的左括号更多,所以不存在e<0的情况。那么可考虑两种情况,即到目前为止:
①删除的左括号数目比右括号多
②删除的左括号数目与右括号数目相同
两种情况下面又有四种情况:

在这里插入图片描述
所以一共8种情况,下面对八种情况进行分析,归纳可得,最终有三种不同情形:

//如果当前删除左右括号数目相同,下面s与t序列又是同左同右,则差值e仍然保持为0
if(e==0&&s[q+1]==t[w+1]) 
	dp[q+1][w+1][0]=true;
//若s下一位是左括号,t依然保留在上一位,则差值e增加一个
if(s[q+1]=='(') 
	dp[q+1][w][e+1]=true;
//如果当前删除左括号数目大于右括号数目,下面s出现右括号,会将差值e抵消一个
else if(e) 
	dp[q+1][w][e-1]=true;

举例说明

思考后感觉还是不太理解。。举个栗子看看一步步是怎么实现的
设输入的两个序列为
(()()())
((()))
过程模拟如下:
在这里插入图片描述

总结

本题简单来说就是:
左右匹配则成功,否则左括号出现增强差距,右括号出现抵消差距
最后答案就是dp[len1][len2][0]是否可行

这道题是真的晕。。欢迎大佬来评论区讲解,哈哈哈

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
动态规划在解决牛客括号问题时,可以按照以下步骤进行: 1. 首先,我们需要理解题目的需求。题目要求我们括号,使得剩下的字符串满足以下条件:左括号和右括号的数量相等,且左括号的位置必须在右括号的前面。 2. 接下来,我们可以使用动态规划来解决这个问题。我们可以定义一个三维的dp数组,其中dp[q][w][e]表示考虑s前q个字符,t前w个字符,且s被除部分左括号数减去右括号数为e时,是否可行(bool类型)。 3. 然后,我们可以从前向后遍历字符串s和t。在每一步中,我们可以考虑两种情况: a. 除的左括号数目比右括号多:我们可以继续除左括号,或者除右括号。即dp[q][w][e] = dp[q-1][w][e+1]或dp[q-1][w][e-1]。 b. 除的左括号数目与右括号数目相同:我们只能除右括号。即dp[q][w][e] = dp[q-1][w-1][e-1]。 4. 最后,我们可以根据dp[len1][len2][0]的值来判断是否可行。其中len1和len2分别表示字符串s和t的长度。 综上所述,通过动态规划的思路,我们可以解决牛客括号的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [动态规划笔记](https://download.csdn.net/download/weixin_38617297/13751806)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [牛客_21303括号_动态规划](https://blog.csdn.net/weixin_45619006/article/details/114650172)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

血月无华AUV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值