ARC074E - RGB Sequence 动态规划

版权声明:_ https://blog.csdn.net/lunch__/article/details/82500945

题面

这个题是一个比较简单的 d p . .

但是还是没有自己想出来…

设状态 d p [ i ] [ j ] [ k ] 表示每种颜色最后出现的位置分别为 i , j , k 的方案数

直接枚举下一个点的颜色转移就可以了

对于约束条件我们把约束挂在右端点 对每个状态预处理一遍是否是合法状态

转移的时候直接往合法状态转移就ok了 复杂度 O ( n 3 + n 2 m )

Codes

#include<bits/stdc++.h>

#define PII pair<int, int> 
#define mp make_pair
#define pb push_back
#define x first
#define y second

using namespace std;

const int N = 300 + 10;
const int mod = 1e9 + 7;

vector<PII> vec[N];

int dp[N][N][N], vis[N][N][N];
int n, m;

void Check(int r, int g, int b) {
    int flag = (r == 0) + (g == 0) + (b == 0);
    if(flag < 2 && (r == g || r == b || g == b)) 
        return void(vis[r][g][b] = 1);
    int now = max(r, max(g, b));
    for(auto v : vec[now]) 
        if((r >= v.x) + (g >= v.x) + (b >= v.x) != v.y)
            return void(vis[r][g][b] = 1);
}

void add(int r, int g, int b, int val) {
    if(!vis[r][g][b]) (dp[r][g][b] += val) %= mod;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("AT2567.in", "r", stdin);
    freopen("AT2567.out", "w", stdout);
#endif

    int x, y, z, ans = 0;

    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; ++ i) {
        scanf("%d%d%d", &x, &y, &z);
        vec[y].pb(mp(x, z));
    }

    for(int i = 0; i <= n; ++ i)
        for(int j = 0; j <= n; ++ j)
            for(int k = 0; k <= n; ++ k) 
                Check(i, j, k);

    dp[0][0][0] = 1;

    for(int i = 0; i <= n; ++ i)
        for(int j = 0; j <= n; ++ j)
            for(int k = 0; k <= n; ++ k)
                if(dp[i][j][k]) {
                    int now = max(i, max(j, k));
                    add(now + 1, j, k, dp[i][j][k]);
                    add(i, now + 1, k, dp[i][j][k]);
                    add(i, j, now + 1, dp[i][j][k]);
                    if(now == n) (ans += dp[i][j][k]) %= mod;
                }

    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/82500945
RGB