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("*********\n")
#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)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
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\n", ans);

    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/buerdepepeqi/p/11273067.html