Array Description
Explicación
Definimos como la cantidad de formas de llenar los primeros elementos del arreglo, de modo que .
Caso base: si , entonces el primer elemento es desconocido y puede ser cualquier cosa de a , así que para todo . En caso contrario, el primer elemento está fijo, así que y todos los demás .
Para , como los elementos adyacentes difieren en a lo sumo , es posible solo si es , o :
Podemos usar la misma idea vista en Grid Paths , donde una celda trampa fuerza porque ningún camino puede terminar ahí. Luego, ponemos cuando el índice está fijo a un valor distinto de , porque ningún arreglo válido puede tener en ese caso.
Calculamos la respuesta final sumando sobre todos los de a .
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1e9 + 7;
int main() {
int n, m;
cin >> n >> m;
vector<int> values(n + 1);
for (int i = 1; i <= n; i++) { cin >> values[i]; }
// dp[position][value] es la cantidad de formas de llenar los primeros "position" elementos
// del arreglo de modo que el elemento en "position" sea igual a value
vector<vector<ll>> dp(n + 1, vector<ll>(m + 1));
// caso base: el primer elemento está fijo o es libre de ser 1..m
if (values[1] == 0) {
for (int j = 1; j <= m; j++) { dp[1][j] = 1; }
} else {
dp[1][values[1]] = 1;
}
for (int position = 2; position <= n; position++) {
int fixed_value = values[position];
for (int val = 1; val <= m; val++) {
// si esta posición está fija y no coincide con j, es inalcanzable
if (fixed_value != 0 && fixed_value != val) { continue; }
// si no, j se puede alcanzar desde j-1, j o j+1 en el índice anterior
dp[position][val] = dp[position - 1][val];
if (val - 1 >= 1) { dp[position][val] += dp[position - 1][val - 1]; }
if (val + 1 <= m) { dp[position][val] += dp[position - 1][val + 1]; }
dp[position][val] %= MOD;
}
}
ll ans = 0;
for (int j = 1; j <= m; j++) { ans = (ans + dp[n][j]) % MOD; }
cout << ans << '\n';
}
import java.io.*;
import java.util.*;
public class ArrayDesc {
public static final int MOD = (int)1e9 + 7;
public static void main(String args[]) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(r.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
// dp[i][j] es la cantidad de formas de llenar los primeros i+1 elementos
// del arreglo de modo que el i-ésimo elemento sea igual a j
int[][] dp = new int[N][M + 1];
// caso base: el primer elemento está fijo o es libre de ser 1..M
StringTokenizer arr = new StringTokenizer(r.readLine());
int first = Integer.parseInt(arr.nextToken());
// si el primer elemento es libre, puede ser cualquier valor de 1..M
if (first == 0) {
Arrays.fill(dp[0], 1);
} else {
// si no, el primer elemento está fijo
dp[0][first] = 1;
}
for (int i = 1; i < N; i++) {
int A = Integer.parseInt(arr.nextToken());
// si esta posición es libre, probar todos los valores 1..M
if (A == 0) {
for (int j = 1; j <= M; j++) {
int[] neighborVals = new int[] {j - 1, j, j + 1};
for (int k : neighborVals) {
// j se puede alcanzar desde j-1, j o j+1 en el índice anterior
if (1 <= k && k <= M) {
dp[i][j] += dp[i - 1][k];
dp[i][j] %= MOD;
}
}
}
} else {
// si esta posición está fija a A,
// solo se puede alcanzar desde A-1, A o A+1
int[] neighborVals = new int[] {A - 1, A, A + 1};
for (int k : neighborVals) {
if (1 <= k && k <= M) {
dp[i][A] += dp[i - 1][k];
dp[i][A] %= MOD;
}
}
}
}
// sumar sobre todos los valores posibles del último elemento
int ans = 0;
for (int j = 1; j <= M; j++) {
ans += dp[N - 1][j];
ans %= MOD;
}
System.out.println(ans);
}
}