版权声明:_ https://blog.csdn.net/lunch__/article/details/82500945
这个题是一个比较简单的
但是还是没有自己想出来…
设状态 表示每种颜色最后出现的位置分别为 的方案数
直接枚举下一个点的颜色转移就可以了
对于约束条件我们把约束挂在右端点 对每个状态预处理一遍是否是合法状态
转移的时候直接往合法状态转移就ok了 复杂度
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;
}