LC.P1155[掷骰子等于目标和的方法数]

方法一:记忆化搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
private static final int MOD = (int) 1e9 + 7;
int[][] cache;

public int numRollsToTarget(int n, int k, int target) {
if (target < n || target > n * k) return 0;
cache = new int[n + 1][target - n + 1];
for (int[] c : cache) {
Arrays.fill(c, -1);
}
return dfs(n, target - n, k);
}

private int dfs(int i, int j, int k) {
if (i == 0) {
return j == 0 ? 1 : 0;
}
if (cache[i][j] != -1) {
return cache[i][j];
}
int ans = 0;
for (int x = 0; x < k && x <= j; ++x) {
ans = (ans + dfs(i - 1, j - x, k)) % MOD;
}
return cache[i][j] = ans;
}
}
  • 时间复杂度:$O(n \times k \times (target-n))$
  • 空间复杂度:$O(n \times (target-n))$

方法二:动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {

private static final int MOD = (int) 1e9 + 7;

public int numRollsToTarget(int n, int k, int target) {
if (target < n || target > n * k) return 0;
int[][] f = new int[n + 1][target - n + 1];
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= target - n; ++j) {
for (int x = 0; x < k && x <= j; ++x) {
f[i][j] = (f[i][j] + f[i - 1][j - x]) % MOD;
}
}
}
return f[n][target - n];
}
}
  • 时间复杂度:$O(n \times k \times (target-n))$
  • 空间复杂度:$O(n \times (target-n))$