下面代码的 dp 数组理论上占用了大约 1GB 内存,但能够通过空间限制只有 512MB 的题目。而如果把判断 if (!dp[i][j][k][l]) continue; 删掉,就会 MLE。这是为什么?
#include <bits/stdc++.h>
using namespace std;
const int N = 102, M = 8005, P = 1000000007;
int n, m, a[N], dp[N][N][M][3];
void add(int &a, int b) { a += b; if (a > P) a -= P; }
int main() {
scanf("%d%d", &n, &m);
if (n == 1) { printf("1"); return 0; }
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
sort(a + 1, a + n + 1, greater<int>());
dp[0][0][0][0] = 1;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k < M; k++) {
for (int l = 0; l <= 2; l++) {
if (!dp[i][j][k][l]) continue;
int p = dp[i][j][k][l];
if (k + 2 * a[i + 1] < M && j + 1 - l > 0) add(dp[i + 1][j + 1][k + 2 * a[i + 1]][l], 1ll * p * (j + 1 - l) % P);
if (k + a[i + 1] < M && l != 2 && j != n) add(dp[i + 1][j + 1][k + a[i + 1]][l + 1], 1ll * p * (2 - l) % P);
if (k - 2 * a[i + 1] >= 0 && j > 0) add(dp[i + 1][j - 1][k - 2 * a[i + 1]][l], 1ll * p * (j - 1) % P);
add(dp[i + 1][j][k][l], 1ll * p * (2 * j - l) % P);
if (k - a[i + 1] >= 0 && l != 2) add(dp[i + 1][j][k - a[i + 1]][l + 1], 1ll * p * (2 - l) % P);
}
}
}
}
int ans = 0;
for (int i = 0; i <= m; i++)
add(ans, dp[n][1][i][2]);
printf("%d\n", ans);
return 0;
}