POJ3704 括号匹配问题 递归方法

目录

题目

算法

完整代码


题目

参考

递归:

https://blog.csdn.net/qq_45272251/article/details/103257953

利用了递归, 但思路稍复杂了

循环:

https://blog.csdn.net/weixin_50340097/article/details/114579805

(看起来是递归其实是循环. 每次递归其实是循环内一次迭代, 没有使用递归的精髓)

https://blog.csdn.net/qq_38851184/article/details/104252592

循环这篇文章的收获, 额外定义状态数组记录对应位置是否匹配.

本文利用递归栈的特性, 力求简明快速地解决这个问题.

算法

首先定义全局变量

(1)待匹配的字符串str2;

(2)定义字符数组state用来记录每个位置的匹配状态. (尚未匹配上的全部标注为$或? , 待匹配上后改回来.)

递归函数输入参数

(1)查找开始位置start

(2)未匹配左括号个数(递归栈内剩余元素)leftnum

递归函数返回值

右括号位置('0'代表无可匹配的右括号)

递归算法流程:

1.如果当前下标对应字符串是'(',记录为'$'

        (1)左括号入栈: 调用递归栈从下一个位置开始寻找左括号. start=pos+1, leftnum=leftnum+1.

        (2)若左括号匹配成功. 配对的左右括号记录为' '. 从已经找到的右括号右侧继续下一次循环.

        (3)若左括号匹配失败, 出栈(返回匹配失败记号0). (所调用的递归已遍历到字符串结束.)

2.如果当前下标对应字符串是')',记录为'?'

        (1)若栈非空(leftnum!=0), 左括号出栈: 即递归函数返回(返回值右括号位置pos). 

        (2)若栈空(leftnum==0): 没有左括号时,说明在递归最外层, 不返回, 继续循环.

3、如果当前下标对应的字符既不是'('也不是')',,记录为' '.

完整代码

#include <bits/stdc++.h>
using namespace std;
#define MAXN 105
 
char str2[MAXN];
char state[MAXN];

int match(int start, int leftnum){
    int right=0;
    if(start>=strlen(str2))//匹配到最后返回
        return 0;
    for(int pos=start;pos<strlen(str2);pos++){
        if(str2[pos]=='('){//情况1.出现左括号
            state[pos]='$';//记录未匹配的左括号
            right=match(pos+1,leftnum+1);
            printf("(:%d; ):%d\n",pos,right);
            if(right>0){//匹配成功
                state[pos]=' ';
                state[right]=' ';
                pos=right;//跳过上次找过的地方
            }else{//如果到最后都没有找到, 说明整个字符串都被遍历过了
                return 0;
            }
            // match(right+1,leftnum);//没有需要匹配的左括号就不入递归栈
            // break;
        }else if(str2[pos]==')'){//情况2. 出现右括号
            state[pos]='?';
            // printf("):%d\n",pos);
            // match(pos+1);//永远由左括号触发下一层递归入栈, 右括号控制出栈
            if(leftnum>0){//栈非空
                return pos;
            }
        }else{//情况3. 左右括号都不是
            state[pos]=' ';
        }
    }
    return 0;
}
 
int main()
{
    while(gets(str2))
    {
        memset(state,'\0',sizeof(state));
        match(0,0);
        puts(str2);
        puts(state);
        cout<<endl;
    }
    return 0;
}

运行效果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
题目描述 给出一个$n\times m$的矩阵,每个位置上有一个非负整数,代表这个位置的海拔高度。一开始时,有一个人站在其中一个位置上。这个人可以向上、下、左、右四个方向移动,但是只能移动到海拔高度比当前位置低或者相等的位置上。一次移动只能移动一个单位长度。定义一个位置为“山顶”,当且仅当从这个位置开始移动,可以一直走到海拔高度比它低的位置上。请问,这个矩阵中最多有多少个“山顶”? 输入格式 第一行两个整数,分别表示$n$和$m$。 接下来$n$行,每行$m$个整数,表示整个矩阵。 输出格式 输出一个整数,表示最多有多少个“山顶”。 样例输入 4 4 3 2 1 4 2 3 4 3 5 6 7 8 4 5 6 7 样例输出 5 算法1 (递归dp) $O(nm)$ 对于这道题,我们可以使用递归DP来解决,用$f(i,j)$表示以$(i,j)$为起点的路径最大长度,那么最后的答案就是所有$f(i,j)$中的最大值。 状态转移方程如下: $$ f(i,j)=\max f(x,y)+1(x,y)是(i,j)的下一个满足条件的位置 $$ 注意:这里的状态转移方程中的$x,y$是在枚举四个方向时得到的下一个位置,即: - 向上:$(i-1,j)$ - 向下:$(i+1,j)$ - 向左:$(i,j-1)$ - 向右:$(i,j+1)$ 实现过程中需要注意以下几点: - 每个点都需要搜一遍,因此需要用双重for循环来枚举每个起点; - 对于已经搜索过的点,需要用一个数组$vis$来记录,防止重复搜索; - 在进行状态转移时,需要判断移动后的点是否满足条件。 时间复杂度 状态数为$O(nm)$,每个状态转移的时间复杂度为$O(1)$,因此总时间复杂度为$O(nm)$。 参考文献 C++ 代码 算法2 (动态规划) $O(nm)$ 动态规划的思路与递归DP类似,只不过转移方程和实现方式有所不同。 状态转移方程如下: $$ f(i,j)=\max f(x,y)+1(x,y)是(i,j)的下一个满足条件的位置 $$ 注意:这里的状态转移方程中的$x,y$是在枚举四个方向时得到的下一个位置,即: - 向上:$(i-1,j)$ - 向下:$(i+1,j)$ - 向左:$(i,j-1)$ - 向右:$(i,j+1)$ 实现过程中需要注意以下几点: - 每个点都需要搜一遍,因此需要用双重for循环来枚举每个起点; - 对于已经搜索过的点,需要用一个数组$vis$来记录,防止重复搜索; - 在进行状态转移时,需要判断移动后的点是否满足条件。 时间复杂度 状态数为$O(nm)$,每个状态转移的时间复杂度为$O(1)$,因此总时间复杂度为$O(nm)$。 参考文献 C++ 代码

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值