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

动态规划(判定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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值