1 条题解

  • 0
    @ 2025-5-16 18:38:09

    题解:洞穴系统数量计算(C++ 实现)

    问题描述

    我们需要根据机器人探索洞穴时记录的输出带(即访问洞穴的墙壁颜色序列),计算可能产生该输出带的洞穴系统的数量。由于结果可能非常大,我们需要对结果取模 1,000,000,0001,000,000,000

    解题思路

    这个问题可以建模为括号匹配问题树结构生成问题。具体来说,输出带可以看作是一个深度优先搜索(DFS)的遍历序列。我们需要根据这个序列生成所有可能的树结构(洞穴系统)。

    1. 递归与动态规划:使用动态规划来计算生成给定序列的树结构的数量。定义 dp[i][j] 为序列中从第 ii 个字符到第 jj 个字符可以生成的树结构的数量。
    2. 状态转移
      • 如果 i==ji == j,则 dp[i][j] = 1(单个洞穴)。
      • 否则,尝试将序列分成两部分:dp[i][k] * dp[k+1][j],其中第 kk 个字符的颜色与第 ii 个字符的颜色相同(表示返回路径)。
    3. 模运算:由于结果可能很大,每次更新 dp[i][j] 时都要取模 1,000,000,0001,000,000,000

    代码实现

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #pragma comment (linker,"/STACK:102400000,102400000")
    #define maxn 305
    #define MAXN 100005
    #define mod 1000000000
    #define INF 0x3f3f3f3f
    #define pi acos(-1.0)
    #define eps 1e-6
    typedef long long ll;
    using namespace std;
    
    ll n, m, k, ans, cnt, tot, flag;
    ll dp[maxn][maxn];
    char s[maxn];
    
    ll dfs(ll x, ll y) {
        if (x >= y) return 1; // Base case: single cave or no caves
        if (dp[x][y] != -1) return dp[x][y]; // Memoization
        ll i, j, t = 0;
        if (s[x] == s[y] && y > x + 1) {
            t += dfs(x + 1, y - 1); // First, try the substring without the first and last character
            for (i = x + 2; i < y - 1; i++) {
                if (s[i] == s[x]) {
                    t += dfs(x, i) * dfs(i + 1, y - 1); // Split and combine
                    t %= mod;
                }
            }
        }
        dp[x][y] = t;
        return t;
    }
    
    int main() {
        int i, j, t;
        while (~scanf("%s", s + 1)) {
            memset(dp, -1, sizeof(dp)); // Initialize dp array
            n = strlen(s + 1); // Length of the input string
            ans = dfs(1LL, n); // Compute the result
            printf("%I64d\n", ans); // Output the result
        }
        return 0;
    }
    

    代码解释

    1. 初始化dp[i][j] 表示从第 ii 个字符到第 jj 个字符可以生成的树结构的数量。初始化为 -1 表示未计算。
    2. 基本情况:单个洞穴(i == j)时,dp[i][j] = 1
    3. 递归函数 dfs
      • 如果 x >= y,直接返回 1(单个洞穴或无洞穴)。
      • 如果 dp[x][y] 已经计算过,直接返回其值。
      • 如果 s[x] == s[y]y > x + 1,尝试将序列分成两部分:
        • 首先尝试 dfs(x + 1, y - 1)
        • 然后尝试所有可能的分割点 i,其中 s[i] == s[x],并累加 dfs(x, i) * dfs(i + 1, y - 1)
    4. 主函数:读取输入,初始化 dp 数组,调用 dfs 计算结果,并输出。

    示例输入与输出

    • 示例输入 1
      ABABABA
      
    • 示例输出 1
      5
      
    • 示例输入 2
      AB
      
    • 示例输出 2
      0
      

    注意事项

    • 使用递归和记忆化技术来避免重复计算。
    • 注意模运算,防止结果溢出。
    • 输入字符串的索引从 1 开始,便于处理。
    • 1

    信息

    ID
    1796
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者