• HDU6578 2019HDU多校训练赛第一场 1001 (dp)


    HDU6578 2019HDU多校训练赛第一场 1001 (dp)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578

    题意:

    你有n个空需要去填,有m个限制,每次限制要求在区间[l,r]内不同的点的个数是为x个,问你填完这n个空的并且满足限制的方案数

    题解:

    定义(dp[i][j][k][t])表示在区间填完前t个位置后,{0,1,2,3}这四个数字最后一次出现的位置为i,j,k,t的方案数

    滚动数组优化掉第一维后,我们转移如下

    dp[p][j][k][t] += dp[p ^1][j][k][t];
    dp[p][i - 1][k][t] += dp[p ^ 1][j][k][t];
    dp[p][i - 1][j][t] += dp[p ^ 1][j][k][t];
    dp[p][i - 1][j][k] += dp[p ^ 1][j][k][t];

    当然 这个时候我们求的是所有的区间,所以我们需要去掉不合法的区间

    去重的时候判断左右端点组成的区间和x是否相符即可

    代码:

    #include <set>
    #include <map>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    const int maxn = 3e2 + 5;
    const int INF = 0x3f3f3f3f;
    const int mod = 998244353;
    const double Pi = acos(-1);
    LL gcd(LL a, LL b) {
        return b ? gcd(b, a % b) : a;
    }
    LL lcm(LL a, LL b) {
        return a / gcd(a, b) * b;
    }
    double dpow(double a, LL b) {
        double ans = 1.0;
        while(b) {
            if(b % 2)ans = ans * a;
            a = a * a;
            b /= 2;
        } return ans;
    }
    LL quick_pow(LL x, LL y) {
        LL ans = 1;
        while(y) {
            if(y & 1) {
                ans = ans * x % mod;
            } x = x * x % mod;
            y >>= 1;
        } return ans;
    }
    vector<pii> vec[maxn];
    int dp[2][maxn][maxn][maxn];
    void MOD(int &x) {
        if(x >= mod) x -= mod;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        int T;
        scanf("%d", &T);
        while(T--) {
            int n, m;
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                vec[i].clear();
            }
            for(int i = 1; i <= m; i++) {
                int l, r, x;
                scanf("%d%d%d", &l, &r, &x);
                vec[r].push_back(make_pair(l, x));
            }
            dp[0][0][0][0] = 1;
    
            for(int i = 1, p = 1; i <= n; i++, p ^= 1) {
                for(int j = 0; j <= i; j++) {
                    for(int k = 0; k <= j; k++) {
                        for(int t = 0; t <= k; t++) {
                            dp[p][j][k][t] = 0;
                        }
                    }
                }
                for(int j = 0; j < i; j++) {
                    for(int k = 0; k <= j; k++) {
                        for(int t = 0; t <= k; t++) {
                            MOD(dp[p][j][k][t] += dp[p ^ 1][j][k][t]);
                            MOD(dp[p][i - 1][k][t] += dp[p ^ 1][j][k][t]);
                            MOD(dp[p][i - 1][j][t] += dp[p ^ 1][j][k][t]);
                            MOD(dp[p][i - 1][j][k] += dp[p ^ 1][j][k][t]);
                        }
                    }
                }
                for(int j = 0; j < i; j++) {
                    for(int k = 0; k <= j; k++) {
                        for(int t = 0; t <= k; t++) {
                            for (auto tmp : vec[i]) {
                                //不合法区间,清零
                                if (1 + (j >= tmp.first) + (k >= tmp.first) + (t >= tmp.first) != tmp.second) {
                                    dp[p][j][k][t] = 0;
                                }
                            }
                        }
                    }
                }
            }
            int ans = 0;
            for (int i = 0, p = n & 1; i < n; i ++)
                for (int j = 0; j <= i; j ++)
                    for (int k = 0; k <= j; k ++)
                        MOD(ans += dp[p][i][j][k]);
            printf("%d
    ", ans);
    
        }
        return 0;
    }
    
  • 相关阅读:
    如何学习WindDbg
    如何在程序中嵌入google的V8 Javascript引擎
    理解程序内存
    如何学习Windows编程
    如何让窗口控件半透明
    Sessions, Window Stations and Desktops
    QQ截图时窗口自动识别的原理
    为什么设计模式在C++社区没有Java社区流行?
    当年写的俄罗斯方块
    如何判断一个C++对象是否在堆上
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/11273067.html
Copyright © 2020-2023  润新知