动态规划(判定DP)——牛客21303

本文探讨了一种使用动态规划方法判断是否能通过删除部分括号将一个合法的括号序列转化为另一个的问题。介绍了算法思路,即通过三维DP数组记录状态,详细解释了状态转移方程,并给出了具体实现代码。

动态规划(判定DP)

——牛客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: 无限

解析:
dp[i][j][k]表示当s1滑动到i时以及s2滑动到j时并且从s1中删去的k="(“的数量-”)"的数量,是否存在;

这里要注意当dp[i][j][k]=1时
当s1[i+1]=s2[j+1] 并且k=0(不然的话一定要删除,前面如果都不匹配了的话这个保留在这里肯定最后到不了要到的字符串)时,就相当于可以不删除,往后一个走所以dp[i+1][j+1][0]=1;

第二种情况: 删除(特别注意就是相等的时候可以删除)
就是在j不动的情况下(相当于去s1[i+1]后面找和这个括号相匹配的括号),删去该s1[i+1]的字母,k通过+1( 删去“(” )或者-1(删去“)” )

还有学到了一个小的技巧:scanf("%s%s",s1+1,s2+1);这样可以方便在后面处理i和j哦;所以后面都是用s1[i+1]来计算的哦,相当于初始地址就是s1+1

#include<bits/stdc++.h>
using namespace std;
int dp[200][200][55];
int main()
{
        char s1[200],s2[200];
        scanf("%s%s",s1+1,s2+1);
        dp[0][0][0]=1;
        int len1=strlen(s1+1),len2=strlen(s2+1);
        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][0]=1;
                        if(s1[i+1]== '(') dp[i+1][j][k+1]=1;
                        //注意这里是if而不是else if(WA了我好久)解析上面有
                        else if(k) dp[i+1][j][k-1]=1;
                    }
                }
            }
        }
        if(dp[len1][len2][0]) printf("Possible\n");
        else printf("Impossible\n");
    return 0;
}

动态规划在解决删除括号问题时,可以按照以下步骤进行: 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.youkuaiyun.com/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.youkuaiyun.com/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 ]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值