AcWing 80. 骰子的点数(Java DP)
原题链接
简单
作者:
Limited
,
2021-02-18 23:34:54
,
所有人可见
,
阅读 263
要点
- $f(i,j)$表示“只考虑扔前$i$次(即前$i$个骰子),且数次总和恰好为$j$的选法集合”,属性:方案数$Sum$
- 状态计算,扔出骰子必有1~6的六种结果,记结果为$k$,则有$f(i,j) = \sum ^{k=6}_{k=1}f(i-1,j-k)$
- 初始状态,$f(0,0)=1$,不使用任何骰子,总和自然为0,视为1种方案
代码 二维
class Solution {
public int[] numberOfDice(int n) {
int[][] f = new int[n + 1][6 * n + 1];
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 6 * n; j++) {
int sum = 0;
for (int k = 1; k <= 6 && k <= j; k++) {
sum += f[i - 1][j - k];
}
f[i][j] = sum;
}
}
int[] ans = new int[6 * n - n + 1];
for(int i = n; i <= 6 * n; i++) ans[i - n] = f[n][i];
return ans;
}
}
代码 空间优化 一维
class Solution {
public int[] numberOfDice(int n) {
int[] f = new int[6 * n + 1];
f[0] = 1;
for (int i = 1; i <= n; i++) {
// 注意更改到一维后 循环逆序 且终点到0 因为f(0,0)=1和f(1···n,0)=0是不同的
for (int j = 6 * n; j >= 0; j--) {
int sum = 0;
for (int k = 1; k <= 6 && k <= j; k++) {
sum += f[j - k];
}
f[j] = sum;
}
}
int[] ans = new int[6 * n - n + 1];
for(int i = n; i <= 6 * n; i++) ans[i - n] = f[i];
return ans;
}
}