删括号--动态规划

1648545-20190709091555626-2045554469.png

采用数组模拟栈的入栈出栈 进行匹配   通过仅有  ~通过率97.3%  因为这类型的解不了 退栈进栈的方式 跟下面代码思路差不多
但是对于下面这种情况的处理无法解决  所以换种思路结合动态规划的思路 每一次查询都有自己作用 并把作用交给下一次查找
(()(()))
()() 
删括号的时候一定要时刻保证左括号数量比右括号多或者等于(最后才等于),我们可以定义dp[i][j][k]表示考虑AA前ii个匹配了BB前jj个AA被删除部分左括号数-右括号数=k是否可行,分类讨论转移即可,最后答案就是dp[n][m][0]
(()......) => ()          对于这种类型不知道删除外面还是只能分类讨论 按删外面试  这里代码的思路有点像“编辑路径”的算法 
只是这里是括号匹配相对比较困难
下面的代码思路是输入字符串转化为目标字符串 这里是第一个字符开始试 第二个试..................

import java.util.*;
public class Main {
    final static int NUM = 105;
    static int dp[][][] = new int[NUM][NUM][NUM];
    static char a[] = new char[NUM];
    static char b[] = new char[NUM];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s1 = sc.nextLine();
        String s2 = sc.nextLine();
        int n = s1.length();
        int m = s2.length();
        for (int i = 1; i <= n; i++) {
            a[i] = s1.charAt(i - 1);
        }
        for (int i = 1; i <= m; i++) {
            b[i] = s2.charAt(i - 1);
        }
        dp[0][0][0] = 1; 
        for(int i = 0 ; i < n ; i++) {
            for(int j = 0 ;j <= m ; j++) {
                for(int k = 0 ; k <= i ; k++) {
                    if(dp[i][j][k]!=0) {//建立在前人的基础上 !=0 证明还有( 还没匹配完
                        if(k==0 && a[i+1]==b[j+1])
                            dp[i+1][j+1][k]=1;
                        if(a[i+1]=='(')
                            dp[i+1][j][k+1]=1;
                        else if(k!=0) 
                            dp[i+1][j][k-1]=1; //能匹配到第一位是 1 为正确答案
                    }
                }
            }
        }
        if(dp[n][m][0]==1)
            System.out.println("Possible");
        else System.out.println("Impossible");
    }
}
#include "pch.h"
#include<iostream>
const int N = 105;
int n, m, i, j, k;
char a[N], b[N];
bool f[N][N][N];
int main()
{
    scanf("%s%s", a + 1, b + 1);
    n = strlen(a + 1), m = strlen(b + 1);
    f[0][0][0] = 1;
    for (i = 0; i < n; ++i)
        for (j = 0; j <= m; ++j)
            for (k = 0; k <= n; ++k)
                if (f[i][j][k])
                    //如果前面状态有可能转化成目标状态,0进行下一操作
                {
                    if (!k && a[i + 1] == b[j + 1])
                        //当删除正好为(),且符合目标状态 
                        f[i + 1][j + 1][k] = 1;
                    if (a[i + 1] == '(')
                        //或者为可删除的状态,先判断(,保证左括号的数量大于右括号
                        //删去(,差值k加一
                        f[i + 1][j][k + 1] = 1;
                    else if (k)
                        //凑够(),删去)差值k减一 也就是a有一部分可以满足条件 继续判断
                        f[i + 1][j][k - 1] = 1;
                }
    //输出()差值k为0的值
    puts(f[n][m][0] ? "Possible" : "Impossible");
}
if else 的疑问
if(a)
b;
if(c)
d;两个if都会进入判断。
if(a)
b;
else if(c)
d;//当满足a的时候就不进入到c的判断,不满足a时,才会去判断c

转载于:https://www.cnblogs.com/cznczai/p/11147986.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值