Java教程

蓝桥杯[十二届][B]-括号序列

本文主要是介绍蓝桥杯[十二届][B]-括号序列,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

题目来自蓝桥杯练习系统

代码链接:https://blog.csdn.net/yanweiqi1754989931/article/details/123093179

这一题在思路不清楚的情况下相当难理解和解决,包括代码,解的话一开始笔者就没什么思路,想出来的方案要么超时要么难以操作

附上代码和解析的思路,希望能帮到和笔者一样被严重困扰的朋友

#include <bits/stdc++.h>
#define int long long
using namespace std;
// 最大长度和模 
const int N = 5010, MOD = 1e9 + 7;
// dp[i][j]代表到第i个符号, 左括号比右括号多i个的添加方案(添加的是左括号) 
int dp[N][N];

inline int calc(string s) {
//    长度
    int len = s.size();
//   初始化
    memset(dp, 0, sizeof dp);
//  读到位置为0时左括号比右括号多0个的解决方案数量为1
    dp[0][0] = 1;
// 依次枚举每个位置 
    for(int i = 1; i <= len; i++) {
// i-1转换为索引 
        if(s[i - 1] == '(') {
            
//            依次左比右多1~len个的情况 
            for(int j = 1; j <= len; j++) {
//                继承上一个的状态,因为读入的是左括号,所以不能加左括号了 
                dp[i][j] = dp[i - 1][j - 1];
            }
        } else {

//            这里处理了j=0的情况,即右括号大于等于左括号时方案数为上一个 相同情况下的方案数和左括号多一个的状态(补全当前的右括号) 
            dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % MOD;
//            如果为右括号,考虑添加左括号,那方案就是之前情况的基础上(j-1的情况,相当于少一个的情况已经考虑了)和,和上一个阶段多一个左括号的情况(多一个左括号,因为没有给出顺序,所以认为是弥补了此次的右括号)         
            for(int j = 1; j <= len; j++) {
                dp[i][j] = (dp[i - 1][j + 1] + dp[i][j - 1]) % MOD;
            }
        }
    }
    
//    调试的输出 
    cout<<s<<endl;
    cout<<"j: ";
    for(int j=0;j<=len;j++){
        printf("%4lld ",j);
    }
    cout<<endl; 
    for(int i = 0; i <= len; i++) {
        cout<<i<<": ";
        for(int j = 0; j <= len; j++) {
            printf("%4lld ",dp[i][j]);
        }
        cout<<endl; 
    }


    for(int i = 0; i <= len; i++) {
//    返回第一个不为零的值,理论上不可能是无解的,为什么取第一个不为0的是因为 存在((((这种情况
// dp4 0 的值为0的,也就是不能再加左括号了 
        if(dp[len][i]) return dp[len][i];
    }


//    否则返回负一
    return -1;
}

//
inline void solve() {
//    输入
    string s;
    cin >> s;

//    镜像一个
    string ss = s;
//    翻转镜像
    reverse(ss.begin(), ss.end());
//    遍历每一个位置,如果是左括号就变成右括号,如果是右括号就变为左括号,相当于翻转
    for(int i = 0; i < ss.size(); i++) {
        ss[i] = (ss[i] == '(') ?  ')' : '(';
    }
//    最终解为两种情况乘积对mod取模 :ss其实是s的镜像比如s:(((),ss:)(((->)))(
// 乘积的原理:形如)(((,此时必然要添加一个左括号以补全左边的右括号,只有一种补全方案,所以1*,而添加右括号的方式有5种,所以是5*
// 所需要添加的左右括号方案便是1*5 
    cout << calc(s) * calc(ss) % MOD << endl;
}

signed main() {
    solve();
    return 0;
}

 

这篇关于蓝桥杯[十二届][B]-括号序列的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!