Leetcode1155. 掷骰子等于目标和的方法数

Every day a Leetcode

题目来源:1155. 掷骰子等于目标和的方法数

解法1:动态规划

设置状态转移矩阵:

vector<vector<int>> dp(n + 1, vector<int>(target + 1, 0));

也可以设成 n*k+1 的大小,大部分情况下设置成 target+1 能节省内存。

初始化时,我们丢第一个骰子,出现 1~k 点数:

// 初始化
for (int i = 1; i <= k && i <= target; i++)
	dp[1][i] = 1;

从上一层结果,丢一个骰子,状态转移到下一层。

设 i 为丢的骰子数,j 为当前层的总点数,x 为当前丢骰子的点数,枚举 x = 1~k,j-x 就是上一层丢的总点数,在满足 j - x >= i - 1 && j - x <= k * (i - 1)的条件下,dp[i][j] += dp[i - 1][j - x],在与 MOD( 1e9 + 7) 取余。

条件j - x >= i - 1 && j - x <= k * (i - 1)的意思是:

前 i-1 个骰子至少要丢 i-1 个点数,最多丢 k * (i - 1) 个点数。事实上,只限定 j - x >= 1 也能通过这些样例。

状态转移方程:

// 动态规划
for (int i = 2; i <= n; i++)
	for (int j = 0; j <= target; j++)
	{
		for (int x = 1; x <= k; x++)
			if (j - x >= i - 1 && j - x <= k * (i - 1))
				dp[i][j] = (dp[i][j] + dp[i - 1][j - x]) % MOD;
	}

代码:

/*
 * @lc app=leetcode.cn id=1155 lang=cpp
 *
 * [1155] 掷骰子等于目标和的方法数
 */

// @lc code=start
class Solution
{
private:
    static const int MOD = 1e9 + 7;

public:
    int numRollsToTarget(int n, int k, int target)
    {
        vector<vector<int>> dp(n + 1, vector<int>(target + 1, 0));
        // 初始化
        for (int i = 1; i <= k && i <= target; i++)
            dp[1][i] = 1;
        // 动态规划
        for (int i = 2; i <= n; i++)
            for (int j = 0; j <= target; j++)
            {
                for (int x = 1; x <= k; x++)
                    if (j - x >= i - 1 && j - x <= k * (i - 1))
                        dp[i][j] = (dp[i][j] + dp[i - 1][j - x]) % MOD;
            }
        return dp[n][target];
    }
};
// @lc code=end

结果:

Leetcode1155. 掷骰子等于目标和的方法数_第1张图片

复杂度分析:

时间复杂度:O(n * k * target)

空间复杂度:O(n * target)

你可能感兴趣的:(Every,day,a,leetcode,1024程序员节,leetcode,算法,动态规划)