leetcode1155 Number of Dice Rolls With Target Sum (tag DP)

You have d dice, and each die has f faces numbered 1, 2, ..., f. Return the number of possible ways (out of fd total ways) modulo 10^9 + 7 to roll the dice so the sum of the face up numbers equals target.git

1.思路 & 解法

从tag来看动态规划DP(dynamic programming)问题,什么样的问题能够用动态规划解?简单而言,若是f(n) = A1 * f(n-k1) + A2 * f(n-k2)+....+Am * f(n-km) + C,A一、A二、C均为常数则可用动态规划解;github

对于此题而言,咱们由常识可知,
"d个f面骰子组成target"="d-1个骰子组成target-1"+"d-1个骰子组成target-2"+"..."+"d-1个骰子组成target-f",
即递推公式:f(d,target) = f(d-1,target-1) + f(d-1,target-2) + .... + f(d-1,target-f);
显然,f(1,1) = 一、f(1,2) = 一、 .... 、f(1,f) = 1;
所以,咱们能够设计一个宽f*d高d 的二维数组,将第一行的数据f(1,1)、f(1,2)、...、f(1,f)设置为1,
则第二行、第三行、....、第n行,都可由公式得出。
而f(d,target)为咱们所需。
复制代码

代码以下:数组

int numRollsToTarget(int d, int f, int target){
    if (d <= 0 || f <= 0 || d * f < target || d > target) {
        return 0;
    }
    int dp_array[d][f * d];
    memset(dp_array, 0, sizeof(int) * d * f * d);
    for (int i = 0; i < f; i++) {
        dp_array[0][i] = 1;
    }
    int mod_number = pow(10, 9) + 7;
    for (int i = 1; i < d; i++) {
        for (int j = i; j < i * f + f && j < target; j++) {
            int sum = 0;
            //注意边界 k >= 0
            for (int k = j - 1; k >= 0 && k >= j - f; k--) {
                sum += dp_array[i - 1][k];
                sum = sum % mod_number;
            }
            dp_array[i][j] = sum;
        }
    }
    return dp_array[d-1][target-1];
}
复制代码

2. 优化

显然,对于这里的递推公式,f(d,target)用不到任何d - 2的结果项f(d-2,m),那么意味着有 有 (d - 2) * d * f的空间浪费了,咱们来优化一下bash

代码:优化

int numRollsToTarget(int d, int f, int target){
    if (d <= 0 || f <= 0 || d * f < target || d > target) {
        return 0;
    }
    int size = d * f;
    int stack1[size];
    int stack2[size];
    memset(stack1, 0, sizeof(int) * size);
    memset(stack2, 0, sizeof(int) * size);
    for (int i = 0; i < f; i++) {
        stack1[i] = 1;
    }
    
    int mod_number = pow(10, 9) + 7;
    for (int i = 1; i < d; i++) {
    	//处理一下不可能项f(d,d-1)
        stack2[i - 1] = 0;
        for (int j = i; j < i * f + f && j < target; j++) {
            int sum = 0;
            //注意边界 k >= 0
            for (int k = j - 1; k >= 0 && k >= j - f; k--) {
                sum += stack1[k];
                sum = sum % mod_number;
            }
            stack2[j] = sum;
        }
        memcpy(stack1, stack2, sizeof(int) * size);
    }
    return stack1[target - 1];
}
复制代码

3. 优化Extra

3.1 空间优化,size = d * f 是否还能够优化,能够改为什么,为何?
3.2 时间优化,memcpy也会消耗时间,如何进行优化?

projectui

相关文章
相关标签/搜索