LeetCode:1155. 掷骰子等于目标和的方法数(C++)

目录

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

题目描述:

实现代码与解析:

动态规划

原理思路:


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

题目描述:

        这里有 n 个一样的骰子,每个骰子上都有 k 个面,分别标号为 1 到 k 。

给定三个整数 n ,  k 和 target ,返回可能的方式(从总共 kn 种方式中)滚动骰子的数量,使正面朝上的数字之和等于 target 。

答案可能很大,你需要对 109 + 7 取模 。

示例 1:

输入:n = 1, k = 6, target = 3
输出:1
解释:你扔一个有 6 个面的骰子。
得到 3 的和只有一种方法。

示例 2:

输入:n = 2, k = 6, target = 7
输出:6
解释:你扔两个骰子,每个骰子有 6 个面。
得到 7 的和有 6 种方法:1+6 2+5 3+4 4+3 5+2 6+1。

示例 3:

输入:n = 30, k = 30, target = 500
输出:222616187
解释:返回的结果必须是对 109 + 7 取模。

提示:

  • 1 <= n, k <= 30
  • 1 <= target <= 1000

实现代码与解析:

动态规划

class Solution {
public:
    int mod = 1e9 + 7;
    int numRollsToTarget(int n, int k, int target) {
        
        vector<int> f(target + 1);
        f[0] = 1; // 初始化,背包大小为0时,没有结果,为一种选择,赋值为1
        // 分组背包,每组只能选一个
        for (int i = 1; i <= n; i ++){ // 分组            
            for (int j = target; j >= 0; j--){ // 体积
                f[j] = 0; // 每个筛子都要放入背包,不能跳过,把上一次的状态清空,这是一维与一般的背包问题不同的地方
                for (int m = 1; m <= k ; m++){ // 价值
                    if (j >= m) { // 剩余体积大才能选,由于优化成了一维,所以j < m时,就直接继承了上一滚动数组的值,不用我们单独赋值了
                        f[j] = (f[j - m] + f[j]) % mod; // f[i][j] = f[i - 1][j - m] + f[i][j]; 求组合个数的递推式,当前方案,加上上一个方案
                    }
                }
            }
        }
        return f[target];
    }
};

原理思路:

        转化为分组背包问题,注释写的非常详细了,不再解析,只解释一些f[i] = 0 的代码。

        这个清零的操作确保了在每个迭代中,f[j] 包含了只考虑当前骰子面值的组合数,而不会累积之前迭代的结果。这是解决问题的关键,以确保计算的正确性,因为你不能跳过任何一个骰子的面值,而传统的分组背包是可以跳过的。

给定一个整组 nums 和一个目标值 target,要求在组中找出两个的和等于目标值,并返回这两个的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历组的所有组合,判断两个的和是否等于目标值。如果等于目标值,则返回这两个的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储组中的元素和对应的索引。遍历组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果组已经排序,可以使用双指针的方法来求解。假设组从小到大排序,定义左指针left指向组的第一个元素,右指针right指向组的最后一个元素。 如果当前两个指针指向的的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cosmoshhhyyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值