• B. Dispersed parentheses 记忆化搜索 + 括号序列的状压表示


    http://codeforces.com/gym/100633/problem/B

    B. Dispersed parentheses
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    The sequence of calculations in arithmetic expressions is usually set by a certain arrangement of parentheses. For example, (3·(2 + 1))·(4 - 5). After deleting all the elements from the expression except parentheses remaining symbols form a parentheses sequence (())(). Let’s assume that adding character «0» does not corrupt the sequence. Let’s call such sequence a disperse parentheses sequence. Also this can be defined as follows:

    • An empty line is a disperse parentheses sequence.
    • If S and T — disperse parentheses sequences, then lines 0S, S0, (S) and ST are also disperse parentheses sequences.

    The depth of disperse parentheses sequence is the maximum difference between the number of opening and closing parentheses in the sequence prefix. (The prefix of line S is the line, which can be obtained from S by deleting symbols from the tail of the line. For example, the prefixes of line «ABCAB» are lines «», «A», «AB», «ABC», «ABCA» and «ABCAB».) Thus, the depth of the sequence «(0)(0())0» equals two (prefix «(0)(0(» contains three openinig and one closing parentheses).

    Calculate the number of possible disperse parentheses sequences n symbols long, that have a depth k.

    Input

    Single line contains space-separated integers n and k (1 ≤ n ≤ 300, 0 ≤ k ≤ n).

    Output

    Output the number of possible disperse parentheses sequences n symbols long, that have a depth k modulo (109 + 9).

    Examples
    Input
    3 0
    Output
    1
    Input
    3 1
    Output
    3
    Input
    3 2
    Output
    0


    这里学到了一个括号序列的状压表示,也就是,要表示一个合法的括号序列,除了用[lef][rig]表示有开括号lef个,
    闭括号rig个之外,还可以用她们的差来表示,直接压缩到一维,[dis]表示两种括号的差值。可知当rig > lef的时候,整个序列是不可能合法的。所以dis < 0直接是0.
    那么设dp[n + 1][dis][k]表示长度是n的括号序列,差值是dis,深度是k的合法情况。

    ans = dp[n + 1][0][k]

    那么可以按位dfs,开始的状态是dis = 0, deep = 0, lef = 0, rig = 0,那么在第cur位,你可以放0,可以放'('或者')'。然后三种情况统计一次的和,就是第cur位的合法情况。

    一开始从dp[1][0][0]出发,推导dp[n + 1][0][k]
    dp[1][0][0]的意思是在第0位,差值是0,深度是k的合法情况数。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    
    int n, k;
    const int MOD = 1e9 + 9;
    const int maxn = 300 + 20;
    bool vis[maxn][maxn][maxn];
    int dp[maxn][maxn][maxn];
    int dfs(int cur, int dis, int deep, int lef, int rig) {
        if (dis < 0 || deep > k) return 0;
        if (vis[cur][dis][deep]) return dp[cur][dis][deep];
        vis[cur][dis][deep] = true;
        if (cur == n + 1) {
            if (dis == 0 && deep == k) {
                return dp[cur][dis][deep] = 1;
            } else return 0;
        }
        LL ans = 0;
        ans += dfs(cur + 1, dis, deep, lef, rig);
        ans += dfs(cur + 1, dis + 1, max(deep, lef + 1 - rig), lef + 1, rig);
        ans += dfs(cur + 1, dis - 1, max(deep, rig + 1 - lef), lef, rig + 1);
        return dp[cur][dis][deep] = ans % MOD;
    }
    void work() {
        scanf("%d%d", &n, &k);
        cout << dfs(1, 0, 0, 0, 0) << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
    
    

    如果不用这个括号序列的状压,则MLE。dp[n][deep][lef][rig]

    2017年7月17日 20:40:26

    现在来看这题。

    其实是从第一位开始构造。

    dp[i][j][k]

    表示构造了i个,左括号和右括号差值是j,现在深度是k,在这个状态下,后面那些序列随便变,最后得到的合法情况数会是dp[i][j][k]

    整个dfs的过程相当于在第cur位放什么的过程。

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    const int MOD = 1e9 + 9;
    LL dp[301][301][301];
    bool vis[301][301][301];
    int n, k;
    LL dfs(int cur, int dis, int depth) {
        if (depth > k) return 0;
        if (cur == n + 1) {
            if (dis == 0 && depth == k) return 1;
            else return 0;
        }
        if (vis[cur][dis][depth]) return dp[cur][dis][depth];
        vis[cur][dis][depth] = true;
        LL ans1 = dfs(cur + 1, dis, depth);
        ans1 += dfs(cur + 1, dis + 1, max(dis + 1, depth));
        if (dis > 0) {
            ans1 += dfs(cur + 1, dis - 1, depth);
        }
        return dp[cur][dis][depth] = ans1 % MOD;
    }
    void work() {
        cin >> n >> k;
        cout << dfs(1, 0, 0) << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code




  • 相关阅读:
    Django REST framework (DRF)框架入门之权限【五】
    Django REST framework (DRF)框架入门之视图【四】
    Django REST framework (DRF)框架入门之视图【三】
    restFul接口设计规范
    Django REST framework (DRF)框架入门之序列化---反序列化【二】
    Django REST framework (DRF)框架入门之序列化【一】
    Vue自动化工具(Vue-cli)基础3
    Vue.js 基础2
    Vue.js 基础1
    Django 下载功能中文文件名问题
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6559147.html
Copyright © 2020-2023  润新知