【XSY3209】RGB Sequence

题目

传送门

解法

\(f_{i, j, k}\)表示有\(i\)个红石块, \(j\)个绿宝石块, \(k\)个钻石块
可以转移到\(f_{p+1, j, k}\)\(f_{i, p+1,k }\)\(f_{i, j, p+1}\)\(p\)\(max(i, j, k)\)

代码

#pragma GCC optimize(3)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int mod = 1000000007;

const int N = 310;

const int M = 310;

struct node
{   int a, b;
    node() { }
    node(int _1, int _2) : a(_1), b(_2) { }
} list[M];

int head[N], nxt[M], tot;

inline void init()
{   memset(head, -1, sizeof(head));
    tot = 0;
}

inline void link(int x, int y, int z)
{   list[tot] = node(y, z);
    nxt[tot] = head[x];
    head[x] = tot++;
}

inline int max(int x, int y) { return x > y ? x : y; }

inline int Plus(int a, int b) { return a + b >= mod ? a + b - mod : a + b; }

int n, m;

inline bool check(int a, int b, int c)
{   int num = max(a, max(b, c));
    for (register int i = head[num]; ~i; i = nxt[i])
    {   int l = list[i].a;
        int cnt = (l <= a) + (l <= b) + (l <= c);
        if (cnt != list[i].b) return 0;
    }
    return 1;
}

int f[N][N][N];

int Dp()
{   f[0][0][0] = 1;
    int Ans = 0;
    register int i, j, k;
    for (i = 0; i <= n; i++)
    {   for (j = 0; j <= n; j++)
        {   for (k = 0; k <= n; k++)
            {   if (!f[i][j][k]) continue;
                if (!check(i, j, k)) { f[i][j][k] = 0; continue; }
                int p = max(i, max(j, k));
//              if (p == n) { Ans = Plus(Ans, f[i][j][k]); continue; }
                f[p+1][j][k] = Plus(f[p+1][j][k], f[i][j][k]);
                f[i][p+1][k] = Plus(f[i][p+1][k], f[i][j][k]);
                f[i][j][p+1] = Plus(f[i][j][p+1], f[i][j][k]);
            }
        }
    }
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= n; j++)
        {   Ans = Plus(Ans, f[i][j][n]);
            Ans = Plus(Ans, f[i][n][j]);
            Ans = Plus(Ans, f[n][i][j]);
        }
    return Ans;
}

int main()
{   scanf("%d %d", &n, &m);
    init();
    for (int i = 1; i <= m; i++)
    {   int l, r, x;
        scanf("%d %d %d", &l, &r, &x);
        if (r-l+1 < x) return 0 & puts("0");
        link(r, l, x);
    }
    printf("%d\n", Dp());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/2016gdgzoi509/p/9477509.html