http://acm.hdu.edu.cn/showproblem.php?pid=6578
题意:一排有N个空格。空格从左到右依次为1、2、…、N。
汤姆正在用{0,1,2,3}中的一个数字填充每个空格。根据他的想法,以下M个条件都必须满足。第i个条件为:
∈[li,ri]的空格中恰好有xi个不同的数。
做法:又是一道不会做的题,看了题解也不会,标程也看不懂,后来才发现,题解上dp[i][j][k][t]表示的是,这个是个数字最后出现的位置排序后是i,j,k,t,从小到大依次递增。而标程是依次递减。。。。我们就来标程的方法吧。这里只需要注意数字的位置就可以了。
表示四个数字出现的最后位置分别是i,j,k,t而且从大到小。如果枚举第i位放的数字
第i位放的数字。如果和第i-1位放的相同则:
第i位放的数字。如果和第j位放的相同则:
第i位放的数字。如果和第j位放的相同则:
第i位放的数字。如果和第t位放的相同则:
显然可以滚动优化。
为什么会是这样的呢,因为在枚举的时候第i位肯定是最大的,肯定第一个是i而紧跟其后就是i-1而其他的位置不变,比如你要放在i位放第j的数字,则原理的位置就成了这样,i-1,i,k,t,重新排序就是如上,但不过这样一个条件就是j严格小于i
当然其他情况下,也可以要求k严格小于j,t严格小于k,但不过因为初始化dp[0][0][0][0],如果这样写会出现状态的无法(虽然后面无法转移是正确的)这样可能会不好写,因此只需要要求i和j就可以了。
关于检查,这个只需要判断在以i为右端点的区间中有满足条件的就可以了。这个看了代码都懂了。
#include "bits/stdc++.h"
using namespace std;
const double eps = 1e-8;
#define reg register
#define lowbit(x) x&-x
#define pll pair
#define pii pair
#define fi first
#define se second
#define makp make_pair
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return (x > 0) ? 1 : -1;
}
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const int N = 100000 + 10;
const int M = 1000 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 998244353;
int dp[2][102][102][102];
int n, m;
vector v[102];
void add(int &x) {
if (x >= mod) x -= mod;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
int l, r, x;
for (int i = 1; i <= n; i++) {
v[i].clear();
}
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &l, &r, &x);
v[r].push_back(makp(l, x));
}
int p = 1;
dp[0][0][0][0] = 1;
for (int i = 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++) {
add(dp[p][j][k][t] += dp[p ^ 1][j][k][t]);
add(dp[p][i - 1][k][t] += dp[p ^ 1][j][k][t]);
add(dp[p][i - 1][j][t] += dp[p ^ 1][j][k][t]);
add(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 g:v[i]) {
if (1 + (j >= g.fi) + (k >= g.fi) + (t >= g.fi) == g.se) continue;
dp[p][j][k][t] = 0;
}
}
}
}
}
p ^= 1;
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
for (int k = 0; k <= j; k++) {
///if (i == j || j == k) printf("%d %d %d %d\n", i, j, k, dp[p][i][j][k]);
add(ans += dp[p][i][j][k]);
}
}
}
printf("%d\n", ans);
}
return 0;
}